Copyright: Copyright 1993 Microsoft Corp.
Citation: Copyright 1993 Microsoft Corporation. All rights reserved.


 Win32 SDK Knowledge Base

Prepared 06/28/94

 Base

 GDI

 Networking

 User

 Win32s

 Tools

 Miscellaneous

THE INFORMATION IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES EITHER EXPRESSED OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS, OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FORGOING EXCLUSION OR LIMITATION MAY NOT APPLY.


Base
 Win32 SDK Knowledge Base

 Base

 SAMPLE: Determining Drive and File System Type

 SAMPLE: Walking a Directory Tree

 SAMPLE: Process API Functions Example

 SAMPLE: Using Thread API Functions

 INF: Objects Inherited Through a CreateProcess Call

 INF: Correct Use of Try/Finally

 INF: Exporting Callback Functions

 SAMPLE: Simple DLL Demonstration

 SAMPLE: Using Anonymous Pipes to Capture Child Process Output

 INF: Consoles Do Not Support ANSI Escape Sequences

 INF: Processes Maintain Only One Current Directory

 SAMPLE: CreateProcess() Priority Demonstration

 SAMPLE: Security API Functions Demonstration

 SAMPLE: Creating Resource-Only DLLs

 SAMPLE: Demonstration of Setting File Attributes

 SAMPLE: Virtual Memory API Function Demonstration

 SAMPLE: Demonstration of Setting Console Text Color

 SAMPLE: Asynchronous I/O Demonstration

 SAMPLE: Communications API Function Demonstration

 SAMPLE: Demonstration of the Console API Functions

 INF: How HEAPSIZE/STACKSIZE Commit > Reserve Affects Execution

 INF: Replacing the Windows NT Task Manager

 INF: AllocConsole() Necessary to Get Valid Handles

 INF: How to Specify Shared and Nonshared Data in a DLL

 INF: Windows NT Servers in Locked Closets

 INF: Apps Should Wait to Free/Re-use WriteFileEx's Buffer

 INF: CreateFile() Using CONOUT$ or CONIN$

 INF: Cancelling Overlapped I/O

 INF: Getting Real Handle to Thread/Process Requires Two Calls

 INF: Exporting Data from a DLL or an Application

 INF: Dynamic Loading of DLLs Under Windows NT

 INF: Implementing a "Kill" Operation in Windows NT

 INF: Default Attributes for Console Windows

 INF: Win32 Priority Class Mechanism and the START Command

 PRB: SEH with Abort() in the try Body

 PRB: SEH with return in the finally Body Preempts Unwind

 INF: Initiating an Unwind in an Exception Handler

 INF: Using volatile to Prevent Optimization of try/except

 INF: Icons for Console Applications

 INF: Memory Handle Allocation

 DOCERR: Return Values of Performance APIs

 INF: Sharing Win32 Services

 INF: Determining Whether Windows NT Is Running

 INF: Process Will Not Terminate Unless System Is In User-mode

 INF: Non-Addressable Range in Address Space

 INF: Alternatives to Using GetProcAddress() With LoadLibrary()

 INF: Secure Erasure Under Windows NT

 INF: WM_COMMNOTIFY is Obsolete for Win32 Applications

 INF: Thread Local Storage Overview

 INF: Precautions When Passing Security Attributes

 INF: Physical Memory Limits Number of Processes/Threads

 SAMPLE: File I/O API Functions Demonstration

 INF: Calculating String Length in Registry

 INF: PAGE_READONLY May Be Used as Discardable Memory

 INF: Clarification of COMMPROP dwMax?xQueue Members

 INF: OpenComm() and Related Flags Obsolete Under Win32

 INF: Global Quota for Registry Data

 INF: Determining Whether App Is Running as Service or .EXE

 INF: VirtualLock() Only Locks Pages into Working Set

 INF: Reducing the Count on a Semaphore Object

 INF: Trapping Floating-Point Exceptions Under Windows NT

 INF: FormatMessage() Converts GetLastError() Codes

 INF: FlushViewOfFile() on Remote Files

 INF: Interprocess Communication Under Windows NT and on Win32s

 SAMPLE: How to Reboot or Shut Down Programmatically

 INF: Validating User Accounts (Impersonation)

 INF: Chaining Parent PSP Environment Variables

 INF: Distinguishing Between Keyboard ENTER and Keypad ENTER

 INF: Win32 .DEF File Usage in Applications and DLLs

 SAMPLE: Demonstration of the Win32 Debug API

 SAMPLE: Demonstration of Using GetLocaleInfoW

 SAMPLE: How to Share Memory Between Processes

 SAMPLE: Demonstrating the Creation of Multiple Threads

 SAMPLE: Constructing and Using a Message Table Resource

 SAMPLE: Sharing Named Memory Between Two Processes

 SAMPLE: Platform Detection

 SAMPLE: Named Pipe Client/Server Demonstration

 SAMPLE: Using API Functions to Access the Registry

 SAMPLE: Using Semaphores to Control Threads

 SAMPLE: Demonstration of Opening and Terminating a Process

 SAMPLE: Using TLS to Store Thread-Specific Data in a DLL

 INF: Priority Inversion and Windows NT Scheduler

 INF: Security and Screen Savers

 SAMPLE: Examining Security Descriptors (SDs)

 SAMPLE: Using Based Pointers to Share Memory

 INF: Default Stack in Win32 Applications

 PRB: Code in DLL Causes Access Violation C00000005

 INF: The Use of the SetLastErrorEx() API

 INF: Windows NT Virtual Memory Manager Uses FIFO

 INF: File Manager Passes Short Filename as Parameter

 SAMPLE: Event Logging

 INF: Getting the Net Time on a Domain

 INF: Increased Performance Using FILE_FLAG_SEQUENTIAL_SCAN

 INF: Noncontinuable Exceptions

 INF: Validating User Account Passwords Under Windows NT

 PRB: Unexpected Result of SetFilePointer() with Devices

 INF: Limit on the Number of Bytes Written Asynchronously

 INF: Setting File Permissions

 INF: Possible Serial Baud Rates on Various Machines

 INF: Using GMEM_DDESHARE in Win32 Programming

 INF: Preventing the Console from Disappearing

 INF: Types of File I/O Under Win32

 INF: Performing a Clear Screen (CLS) in a Console Application

 INF: Win32 Equivalents for C Run-Time Functions

 SAMPLE: Code Demonstration to Put a DACL on Floppy Disk Drives

 SAMPLE: A Simple Service

 INF: FILE_FLAG_WRITE_THROUGH and FILE_FLAG_NO_BUFFERING

 PRB: SetConsoleOutputCP() Not Functional

 INF: Direct Drive Access Under Win32

 INF: Restriction on Named-Pipe Names

 INF: Replacing the Shell (Program Manager)

 INF: CPU Quota Limits Not Enforced

 INF: Time Stamps Under the FAT File System

 INF: Examining the dwOemId Value

 INF: Interrupting Threads in Critical Sections

 INF: Changes to DLL Makefiles for Windows NT 3.1 Release

 INF: Impersonation Provided by ImpersonateNamedPipeClient()

 INF: Application Exception Error Codes

 INF: Gaining Access to ACLs

 INF: Administrator Access to Files

 INF: Passing Security Information to SetFileSecurity()

 INF: Extracting the SID from an ACE

 INF: How to Add an Access-Allowed ACE to a File

 INF: Computing the Size of a New ACL

 INF: FILE_READ_EA and FILE_WRITE_EA Specific Types

 INF: System GENERIC_MAPPING Structures

 INF: Why LoadLibraryEx() Returns an HINSTANCE

 INF: Passing a Pointer to a Member Function to the Win32 API

 INF: Detecting Closure of Command Window from a Console App

 INF: Definition of a Protected Server

 INF: How Windows NT Handles Floating-Point Calculations

 INF: Security Attributes on Named Pipes

 INF: Using Temporary File Can Improve Application Performance

 INF: Copy on Write Page Protection for Windows NT

 INF: Detecting Logoff from a Service

 INF: Mapping .INI File Entries to the Registry

 INF: Creating a Font for Use with the Console

 INF: Monitoring a Log File for an Event

 INF: Cancelling WaitCommEvent() with SetCommMask()

 BUG: Redirecting Output to an MS-DOS Application

 INF: SetErrorMode() Is Inherited

 INF: Calling CRT Output Routines from a GUI Application

 INF: Getting and Using a Handle to a Directory

 INF: Named Pipe Buffer Size

 INF: The Use of PAGE_WRITECOPY

 BUG: Problems with Local/Global Memory Management APIs

 BUG: AllocConsole() Does Not Set Error Code on Failure

 INF: Setting the Console Configuration

 INF: First and Second Chance Exception Handling

 INF: Critical Sections Versus Mutexes

 PRB: GetPrivateProfileSection() Can Read Only 32K Sections

 INF: Using NTFS Alternate Data Streams

 INF: RegSaveKey() Requires SeBackupPrivilege

 INF: Sharing Objects with a Service

 INF: Accessing the Macintosh Resource Fork

 FIX: VirtualLock() on File-Mapped Pages Hangs Computer

 INF: Retrieving Counter Data From the Registry

 INF: Replace IsTask() with GetExitCodeProcess()

 INF: Accessing the Event Logs

 INF: CreateFileMapping() SEC_* Flags

 DOCERR: WM_COPYDATA Is Also Supported on Win32s

 INF: Use LoadLibrary() on .EXE Files Only for Resources

 INF: Working Set Size, Nonpaged Pool, and VirtualLock()

 INF: Sharing All Data in a DLL

 PRB: ERROR_INVALID_PARAMETER from WriteFile() or ReadFile()

 PRB: Can't Increase Process Priority

 INF: New Owner in Take-Ownership Operation

 INF: Checking for Administrators Group

 INF: Creating a World SID

 INF: Looking Up the Current User and Domain

 INF: Security Context of Child Processes

 INF: Taking Ownership of Registry Keys

 PRB: GetExitCodeProcess Always Returns 0 for 16-Bit Processes

 INF: ERROR_BUS_RESET May Be Benign

 INF: Possible Cause for ERROR_INVALID_FUNCTION

 DOCERR: EofChar Field of DCB Structure Is Not Supported

 INF: Retrieving Time-Zone Information

 INF: Timer Resolution in Windows NT

 DOCERR: References to APIs that Do Not Exist

 INF: Long Filenames on Windows NT FAT Partitions

 INF: Limits on Overlapped Pipe Operations

 INF: Accessing the Application Desktop from a Service

 INF: Clarification of SearchPath() Return Value

 INF: Filenames Ending with Space or Period Not Supported

 INF: Getting Floppy Drive Information

 INF: How to Gracefully Fail at Service Start

 INF: Specifying Serial Ports Larger than COM9

 INF: Services and Redirected Drives

 INF: Determining the Maximum Allowed Access for an Object

 PRB: AccessCheck() Returns ERROR_INVALID_SECURITY_DESCR

 INF: Adding Categories for Events

 INF: Creating Access Control Lists for Directories

 PRB: RegCreateKeyEx() Gives Error 161 Under Windows NT 3.5

 GDI

 Networking

 User

 Win32s

 Tools

 Miscellaneous


GDI
 Win32 SDK Knowledge Base

 Base

 GDI

 SAMPLE: World Coordinate Transform

 SAMPLE: AngleArc Demonstration Program

 SAMPLE: Demonstration of Using System Info API

 SAMPLE: StretchBlt Demonstration

 SAMPLE: Using Region-Related API Functions

 SAMPLE: PlgBlt Demonstration

 INF: General Overview of Win32s

 SAMPLE: GetDeviceCaps() Demonstration Program

 SAMPLE: PolyDraw Function Demonstration

 PRB: Saving/Loading Bitmaps in .DIB Format on MIPS

 INF: Using GetDIBits() for Retrieving Bitmap Information

 INF: Win32 Subsystem Object Cleanup

 INF: Transparent Blts in Windows NT

 INF: PSTR's in OUTLINETEXTMETRIC Structure

 PRB: IsGdiObject() Is Not a Part of the Win32 API

 INF: Use of DocumentProperties() vs. ExtDeviceMode()

 INF: Using Device Contexts Across Threads

 INF: 16 and 32 Bits-Per-Pel Bitmap Formats

 SAMPLE: Demonstrating GDI and User APIs in Fractals

 SAMPLE: Demonstration of the Win32 Font API Functions

 SAMPLE: Enhanced Metafile Editor

 INF: Uniqueness Values in User and GDI Handles

 INF: Advantages of Device-Dependent Bitmaps

 INF: DEVMODE and dmSpecVersion

 SAMPLE: Demonstration of Printing with Windows NT

 SAMPLE: Fractal Screen Saver Demonstration

 INF: Memory Handles and Icons

 INF: Use 16-Bit .FON Files for Cross-Platform Compatibility

 INF: Tracking Brush Origins in Windows NT

 INF: Calculating the TrueType Checksum

 INF: Symbolic Information for System DLLs

 INF: Creating a Logical Font with a Nonzero lfOrientation

 PRB: StreBlt Sample Causes Windows NT to Stop Responding

 FIX: SetCaret API May Not Work Correctly in Win32 Applications

 INF: ClipCursor() Requires WINSTA_WRITEATTRIBUTES

 INF: Retrieving DIBs from the Clipboard

 DOCERR: LoadCursorFromFile() and SetSystemCursor() Are Missing

 INF: Querying Device Support for MaskBlt

 DOCERR: DeviceCapabilitiesEx Not Implemented in Windows NT 3.1

 INF: Win32s 1.1 Limitations

 INF: Printing Offset, Page Size, and Scaling with Win32

 INF: Accessing the Application Desktop from a Service

 Networking

 User

 Win32s

 Tools

 Miscellaneous


Networking
 Win32 SDK Knowledge Base

 Base

 GDI

 Networking

 INF: Distributed Computing Environment (DCE) Compliance

 PRB: WSAAsyncSelect() Notifications Stop Coming

 INF: Writing a Telnet Client

 INF: NetBIOS Name Table and NCBRESET

 INF: Using RPC Callback Functions

 INF: RPC Can Use Multiple Protocols

 INF: Tuning Sessions, Names, and NCBs for NetBIOS Applications

 INF: Supported Versions of Windows Sockets

 Location of WNet* API Functions

 PRB: RPC Installation Problem

 INF: RpcNsxxx() APIs Not Supported by Windows NT Locator

 INF: Using ReadFile() and WriteFile() on Socket Descriptors

 FIX: NDISCloseFile() Does Not Free Image Buffer

 FIX: APIs Do Incorrect Comparisons

 INF: Host Name May Map to Multiple IP Addresses

 PRB: Winsock select() Returns WSAENOTSOCK

 INF: Windows NT Support for the MS-DOS LAN Manager APIs

 INF: Availability of Microsoft Network SDKs

 INF: MIDL 1.0 and MIDL 2.0 Full Pointers Do Not Interoperate

 User

 Win32s

 Tools

 Miscellaneous


User
 Win32 SDK Knowledge Base

 Base

 GDI

 Networking

 User

 INF: Global Classes in Win32

 INF: Unicode Conversion to Integers

 INF: Multiline Edit Control Limits in Windows NT

 INF: Tips for Writing Multiple-Language Scripts

 INF: Writing Multiple-Language Resources

 INF: Getting the WinMain() lpCmdLine in Unicode

 INF: Creating Windows in a Multithreaded Application

 INF: Multiple Desktops Under Windows NT

 INF: DDEML Application-Instance IDs Are Thread Local

 INF: Freeing PackDDElParam() Memory

 INF: Uniqueness Values in User and GDI Handles

 INF: SendMessage() in a Multithreaded Environment

 INF: Window Message Priorities

 INF: NULL is a Valid Return From SetWindowsHook()

 INF: LB_GETCARETINDEX Returns 0 for Zero Entries in List Box

 INF: SetActiveWindow() and SetForegroundWindow() Clarification

 INF: UNICODE and _UNICODE Needed to Compile for Unicode

 INF: Memory Handles and Icons

 INF: Using SetThreadLocale() for Language Resources

 PRB: AttachThreadInput() Resets Keyboard State

 INF: System Versus User Locale Identifiers

 PRB: Unicode ChooseColor() Help Button May Crash Common Dialog

 INF: Debugging a System-Wide Hook

 DOCERR: WM_ENTERIDLE Documentation Is Misleading

 INF: SetTimer() Should Not Be Used in Console Applications

 INF: The SBS_SIZEBOX Style

 INF: Clarification of the "Country" Setting

 PRB: CloseClipboard() Suggests Calling DuplicateHandle()

 INF: Differences Between hInstance on Win 3.1 and Windows NT

 INF: Unicode Implementation in Windows NT 3.1

 INF: Unicode Font UCLUCIDA.TTF Renamed to L_10646.TTF

 INF: Propagating Environment Variables to the System

 INF: Mapping .INI File Entries to the Registry

 INF: 32-Bit Scroll Ranges

 INF: How Keyboard Data Gets Translated

 INF: COMCTL32 APIs Unsupported in the Win32 SDK

 INF: Win32 Shell Dynamic Data Exchange (DDE) Interface

 INF: Win32 Drag and Drop Server

 FIX: Low Memory Condition Cause APIs to Return Random Values

 INF: Development Tools Do Not Accept Unicode Text

 INF: Identifying a Previous Instance of an Application

 INF: Retrieving DIBs from the Clipboard

 INF: Using SendMessageTimeout() in a Multithreaded Application

 INF: Journal Hooks and Compatibility

 INF: Hooking Console Applications and the Desktop

 PRB: GetOpenFileName() and Spaces in Long Filenames

 INF: MultiByteToWideChar() Codepages CP_ACP/CP_OEMCP

 INF: Replacing Windows NT 3.1 Control Panel's Mouse Applet

 DOCERR: DragQueryFile() Return Code Can Be Misleading

 Win32s

 Tools

 Miscellaneous


Win32s
 Win32 SDK Knowledge Base

 Base

 GDI

 Networking

 User

 Win32s

 INF: General Overview of Win32s

 PRB: Win32s GetVolumeInformation() Returns 0x12345678

 INF: Calling a Win32 DLL from a Win16 App on Win32s

 INF: Win32s Message Queue Checking

 PRB: _getdcwd() Returns the Root Directory Under Win32s

 FIX: GetVersion() Returns Invalid Value Under Win32s

 INF: Support for Sleep() on Win32s

 INF: Win32s Translated Pointers Guaranteed for 32K

 INF: Debugging Win32s Applications

 INF: GetCommandLine() Under Win32s

 INF: Win32s NetBIOS Programming Considerations

 INF: Win32s Cannot Support _environ in DLLs

 INF: Debugging Universal Thunks

 INF: Using Windows Sockets Under Win32s and WOW

 INF: Win32s and Windows NT Timer Differences

 INF: Using Serial Communications Under Win32s

 INF: Using VxDs and Software Interrupts Under Win32s

 INF: Getting Resources from 16-Bit DLLs Under Win32s

 INF: Sharing Memory Between 32-Bit and 16-Bit Code on Win32s

 INF: Troubleshooting Win32s 1.1 Installation Problems

 INF: Opening Named Pipes on Win32s

 INF: DIB_PAL_INDICES and CBM_CREATEDIB Not Supported in Win32s

 PRB: "Routine Not Found" Errors in Windows Help

 INF: Win32s and LAN Manager APIs

 INF: Creating Instance Data in a Win32s DLL

 BUG: Problems with Win32s CreateFileMapping()

 INF: Availability of Win32s 1.1a and Later

 INF: Detecting the Presence of NetBIOS in Win32s

 INF: How Win32 Applications Are Loaded Under Windows

 INF: NetBIOS on Win32s Requires GlobalAlloc()'d Memory

 DOCERR: Errors in Win32s Compatibility

 BUG: Win32s 1.1 Bug List

 INF: Converting a Linear Address to a Flat Offset on Win32s

 PRB: Page Fault in WIN32S16.DLL Under Win32s

 INF: Win32s Device-Independent Bitmap Limit

 PRB: Display Problems with Win32s and the S3 Driver

 Tools

 Miscellaneous


Tools
 Win32 SDK Knowledge Base

 Base

 GDI

 Networking

 User

 Win32s

 Tools

 INF: Using a Mouse with MEP Under Windows NT

 INF: RCDATA Begins on 32-Bit Boundary in Windows NT

 INF: Format for LANGUAGE Statement in .RES Files

 PRB: Selecting Overlapping Controls in Dialog Editor

 INF: Dynamic Loading of DLLs Under Windows NT

 INF: Use of DLGINCLUDE in Resource Files

 INF: Using the C Run Time

 INF: CTYPE Macros Function Incorrectly

 INF: Thread Local Storage Overview

 INF: Postmortem Debugging Under Windows NT

 INF: Size Comparison of 32-Bit and 16-Bit x86 Applications

 INF: CTRL+C Exception Handling Under WinDbg

 INF: Debugging DLLs Using WinDbg

 INF: Language ID Needed for RC.EXE

 INF: Watching Local Variables That Are Also Globally Declared

 INF: Determining Memory Usage Under Windows NT

 FIX: Global Constructors Not Called in Alpha DLLs

 PRB: MS-SETUP Uses \SYSTEM Rather Than \SYSTEM32

 INF: Debugging a Service with WinDbg

 PRB: Cannot Compile from Win32 SDK M Editor (MEP.EXE)

 INF: Source-level Debugging Under NTSD

 INF: Compile Errors Caused by Missing Option -D_X86_

 PRB: Debugging the Open Common Dialog Box in WinDbg

 INF: WinDbg Message "Breakpoint Not Instantiated"

 INF: Enabling Disk Performance Counters

 PRB: Data Section Names Limited to Eight Characters

 INF: Setting Dynamic Breakpoints in WinDbg

 PRB: Debugging an Application Driven by MS-TEST

 INF: Interpreting Executable Base Addresses

 INF: Debugging Console Apps Using Redirection

 PRB: MIPS Compiler Assertion with C version 8.0

 INF: Example of Importing Functions

 INF: Choosing the Debugger That the System Will Spawn

 INF: Cannot Load <exe> Because NTVDM Is Already Running

 INF: Viewing Globals Out of Context in WinDbg

 PRB: RC Does Not Support __DATE__ or __TIME__

 PRB: Unable to Freeze One Thread in WinDbg

 PRB: WinDbg FIND Dialog Box Slows Down the System

 INF: Debugging the Win32 Subsystem

 INF: Differences Between the Win32 SDK and 32-Bit VC++

 INF: Listing the Named Shared Objects

 PRB: RW1016 Error Due to Unexpected End of File (EOF)

 INF: Additional Remote Debugging Requirement

 PRB: Problems with the Microsoft Setup Toolkit

 FIX: Internal Error from NetUserEnum()

 INF: Changes to the MSTest WFndWndC()

 INF: Sharing All Data in a DLL

 INF: Creating Instance Data in a Win32s DLL

 DOCERR: Errors in Win32s Compatibility

 BUG: Win32s 1.1 Bug List

 INF: Win32s 1.1 Limitations

 PRB: "Out of Memory Error" in the Win32 SDK Setup Sample

 PRB: Page Fault in WIN32S16.DLL Under Win32s

 INF: Win32 SDK 3.5 LINK32.EXE Calls CVTRES.EXE

 Miscellaneous


Miscellaneous
 Win32 SDK Knowledge Base

 Base

 GDI

 Networking

 User

 Win32s

 Tools

 Miscellaneous

 INF: Win32 Subsystem Object Cleanup

 INF: No Subsystem Developer Kit or Support for Such a Kit

 INF: Running Bound Applications Under Windows NT

 PRB: GP Fault in OS/2 Subsystem

 INF:  Binary and Source Compatibility Under Windows NT

 INF: Named Pipes Under WOW

 INF: Some Subsystems Persevere Through Logons

 INF: Binary Compatibility Basics

 INF: Win32 Graphical Setup Not Supported Over Network Drives

 INF: Specifying Filenames Under the POSIX Subsystem

 INF: Detecting Windows NT from an MS-DOS Application

 INF: LIM-EMS Memory Limitations in a Windows NT VDM

 INF: SHARE.EXE Functionality Built into Windows NT

 INF: LAN Manager API Support in OS/2 Subsystem

 INF: How POSIX Applications are Recognized

 INF: Determining Whether a WOW App is Running in Enhanced Mode

 PRB: Error in Win32 SDK Install Program MANUAL.BAT

 INF: Symbolic Information for System DLLs

 PRB: Win32 SDK and VC++ NT Help Files Are Incompatible

 INF: Migrating Windows NT Program Groups and the Desktop

 INF: Starting and Terminating 16-Bit Windows Applications

 INF: Troubleshooting Win32s 1.1 Installation Problems

 INF: Making a Callback When Using Generic Thunks

 INF: Running a Win16 Application in Its Own VDM


SAMPLE: Determining Drive and File System Type

Article ID: Q81719

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The DRIVES sample demonstrates how the GetDriveType() and

GetVolumeInformation() APIs determine all logical drives on a system, their

disk type (local, remote, CD-ROM, and so on), and their file system type

(FAT, HPFS, etc.).

This sample is included with the Microsoft Win32 Software Development

Kit (SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The additional APIs used in this sample, GetLogicalDrives() and

GetLogicalDriveStrings(), are not required to determine the drive and file

system type, but are included as an example of how these APIs can

enhance the efficiency of disk querying API calls.

When a drive type is removable (for example, a floppy disk drive), then

additional precautions are taken before accessing this drive. A validation

check is made to see if media exists in the drive before proceeding. A

simple test of opening any file in the root directory of the removable

media drive using the OpenFile() API function determines the media's

presence. If the OpenFile() call returns a handle, then media is present

and further disk querying calls are safely made on the logical drive. If

the OpenFile() call fails, then no media is present and no further attempts

to query this drive are allowed.

NOTE: in order to eliminate an unwanted pop-up, prompting the user to

insert a disk in the drive, from being generated by the operating system,

the error mode is temporarily adjusted, using SetErrorMode(), to allow any

OpenFile() errors to immediately return to the calling routine.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseFileio


SAMPLE: Walking a Directory Tree

Article ID: Q81720

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The WALK sample demonstrates how to recursively find all subdirectories

under the current working directory.

This sample is included with the Microsoft Win32 Software Development

Kit (SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

Starting with the current working directory, a call is made to the Walk

function which will find all subdirectories in the current working

directory. When a subdirectory is found, the current working directory is

changed to this subdirectory and another, recursive call is made to Walk,

which again will find all subdirectories in this new current working

directory. Once all subdirectories for the current working directory have

been found, the current working directory is changed up one level (..).

When the original current working directory is re-entered, then the

recursive process stops.

Additional reference words: FindFirstFile GetCurrentDirectory

SetCurrentDirectory FindNextFile GetFileAttributes

KBCategory: Ref

KBSubcategory: CodeSam BseFileio


SAMPLE: Process API Functions Example

Article ID: Q81825

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The PROCESS sample application provides a simple interface to the

CreateProcess() and TerminateProcess() functions. To create a process,

the user is presented with a common dialog box for selecting a file.

In this case, the file must have an extension of .EXE. Processes that

are started are presented in a list box. Any of the processes can be

selected in the list box and then terminated.

This sample is included with the Microsoft Win32 Software Development

Kit (SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

Warning: "TerminateProcess() is used to cause all of the threads

within a process to terminate. While TerminateProcess() will cause all

threads within a prcess to terminate, and will cause an application to

exit, it does not notify DLLs that the process is attached to that the

process is terminating. TerminateProcess() is used to unconditionally

cause a process to exit. It should only be used in extreme

circumstances. The state of global data maintained by DLLs may be

compromised if TerminateProcess() is used rather than ExitProcess()."

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseProcThrd


SAMPLE: Using Thread API Functions

Article ID: Q81826

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The THREADS sample application shows how to use the APIs

SetThreadPriority(), SuspendThread(), and ResumeThread().

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

To use THREAD, start the application. Two threads will be created; one will

draw a red rectangle and the other a green rectangle. Both of these

rectangles move about the window; their speed and behavior is based on the

thread priority and its resumed/suspended status. The priority and status

are set through menu selections.

Of special interest is the suspension count. The system keeps track of the

number of times a thread has been suspended and resumed. Each time the

thread is suspended, the count is incremented; each time it is resumed, the

count is decremented. The suspension count can either be tracked by

applications manually, the same way this sample application does, or the

return value from ResumeThread and SuspendThread can be used to obtain the

previous suspension count before the call was made. Only when the

suspension count is zero will the thread run.

A thread now has seven levels of priority exposed at the API level:

   THREAD_PRIORITY_IDLE

   THREAD_PRIORITY_LOWEST

   THREAD_PRIORITY_BELOW_NORMAL

   THREAD_PRIORITY_NORMAL

   THREAD_PRIORITY_ABOVE_NORMAL

   THREAD_PRIORITY_HIGHEST

   THREAD_PRIORITY_TIME_CRITICAL

Note, caution should be used when setting a thread priority to

THREAD_PRIORITY_TIME_CRITICAL. This level is high enough to interfere with

the application's window performance, and interfere with other applications

running on the system.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseProcThrd


INF: Objects Inherited Through a CreateProcess Call

Article ID: Q83298

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The objects inherited by a process started by a call to CreateProcess() are

those objects that you can get a handle to and on which you can use the

CloseHandle() function. These objects include the following:

   Processes

   Events

   Semaphores

   Mutexes

   Files (including file mappings)

   Standard input, output, or error devices

However, the new process will only inherit objects that were marked

inheritable by the old process.

These are duplicate handles. Each process maintains memory for its own

handle table. If one of the processes modifies its handle (for example,

closes it or changes the mode for the console handle), other processes will

not be affected.

Processes will also inherit environment variables, the current directory,

and priority class.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseProcThrd


INF: Correct Use of Try/Finally

Article ID: Q83670

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Try/finally, used correctly, helps to provide a robust application.

However, if used incorrectly it can cause unnecessary overhead. any

flow of control out of the try body of try/finally is an abnormal

termination that can cause hundreds of instructions to be executed on

an x86 system, and thousands on a MIPS machine, even if control leaves

the try body via a control statement on the very last statement of the

try body. The language definition states that control must leave the

try body sequentially for normal termination to occur (that is,

execution falls through the bottom of the try body).

The following sample demonstrates an incorrect use of try/finally:

/* Incorrect use of try/finally */

VOID

function (

   DWORD ... P1,

      .

   DWORD ... Pn

   )

{

   try {

       if (...) {

           .

           .

           return;

       }

           .

           .

   } finally {

      .

      .

   }

   return;

}

The overhead can be avoided in the above example by moving the return

AFTER the end of the finally clause. The following provides more

detail on the correct use of try/finally.

MORE INFORMATION

================

Execution of a termination handler due to abnormal termination of a

try body is expensive. Abnormal termination occurs when control leaves

a try body in any way other than by falling through the bottom.

Intentionally branching out of a try body is still an abnormal

termination.

In the above example, abnormal termination of the try body occurs if

the return in the middle of the try body is executed. If the predicate

of the if is false, then extremely efficient execution of the finally

clause occurs because this is not abnormal termination and the finally

clause is called directly by inline code.

When abnormal termination occurs hundreds to thousands of instructions

are executed because an unwind must be executed, which must search

backward through frames to determine if any termination handlers

should be called. On an x86 system, this executes the C run-time

handler and examines the handler list. On a MIPS machine, this also

causes the function table to be searched and the prologue of each

intervening function to be executed backwards interpretively.

You should always avoid the execution of a termination handler as a

result of the abnormal termination of a try body by a return, or other

direct flow of control out of the try body. Abnormal termination

occurs whenever control leaves the try body other than by falling

through the bottom. This can occur because of a return, goto,

continue, or break. It can also occur because of an exception, which

presumably cannot be avoided.

In the above example, abnormal termination in the nonexception case

can be eliminated easily as follows:

/* Correct use of try/finally */

VOID

function (

   DWORD ... P1,

      .

      .

   DWORD ... Pn

   )

{

   try {

       if (...) {

           .

           .

       } else {

           .

           .

       }

   } finally {

      .

      .

   }

   return;

}

Now both clauses of the if fall through to the termination handler in

all but exceptional cases and execute the termination handler in the

most efficient way. This also has the same logical execution as the

previous sample.

In summary, the correct use of try/finally is a powerful method to

help you write robust applications. Care should be taken to ensure the

correct use of try/finally.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseExcept


INF: Exporting Callback Functions

Article ID: Q83706

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

It is not necessary for Win32 applications to export callback functions.

Windows versions 3.1 and earlier (Win16) need callback functions primarily

for fixing references to global data and ensuring that EMS memory is not

paged out. Neither of these situations applies to the Windows NT operating

system.

MORE INFORMATION

================

Exports are necessary for any function that must be located at either

1) Run time via GetProcAddress() (dynamic linking)

   -or-

2) Load time via an import library (static linking)

Both of these linking methods require that the name or ordinal number of

the export be known and that their names (or ordinal numbers) be present in

the executable's exported entry table. This enables Windows to determine

the addresses at run time.

Static linking is done by the loader, which performs this lookup for all of

the imported entry points that an executable needs (normally by ordinal

number). In dynamic linking, the system scans by ordinal number or by name

through the DLL (Dynamic Link Library) exports table.

In Win16, exported entries are automatically fixed by the linker to adjust

to the appropriate data segment. Exporting entries on Win32 just adds them

to the module's exported names and ordinal numbers table; the linker does

not need to "fix" them. For code compatibility with Win16, you may want to

continue to use MakeProcInstance() and export all callbacks. This macro

does nothing on Windows NT.

In short,

                    On Windows                       On Windows NT

                    ---------------------------      -----------------

   Callbacks        Export or use MakeProcInstance   Use address of fn

   GetProcAddress   Must export                      Must export

   Static linking   Must export                      Must export

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseDll


SAMPLE: Simple DLL Demonstration

Article ID: Q83932

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The SIMPLDLL sample provides a generic DLL template. Also included are two

small test applications, LINKTEST and LOADTEST, which demonstrate load-time

linking (to a DLL import library) and dynamic loading, respectively.

MORE INFORMATION

================

THE_DLL contains a skeleton DLL (dynamic-linked library) entry point and

five exported functions with varying parameter lists. A resource file

(containing a dialog box template) is also used.

LINKTEST is a small application that links with the THE_DLL's import

library, and allows the user to make calls into THE_DLL (via menu item

selections).

LOADTEST is a small application that loads THE_DLL at run time and calls

the GetProcAddress() function to retrieve the addresses of THE_DLL's

exported functions. Again, the user is allowed to make calls into THE_DLL.

Additional reference words: GetModuleFileName LoadLibrary GetProcAddress

KBCategory: Ref

KBSubcategory: CodeSam BseDll


SAMPLE: Using Anonymous Pipes to Capture Child Process Output

Article ID: Q84082

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The INHERIT sample demonstrates how to redirect standard output and

standard error to an anonymous pipe using two different techniques: passing

anonymouse pipe handles to the child in the STARTUPINFO structure, and by

setting anonymous pipe handles as the standard handles with the

SetStdHandle API and having the child process inherit them.

In the sample, a child process is started whose standard output and

standard error handles have been redirected to an anonymous pipe. The

parent reads out of this pipe and puts the data to both the console and to

a log file specified on the command line.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

Additional reference words: 3.10 CloseHandle CreateProcess ReadFile

CreateFile GetLastError CreatePipe WriteFile

KBCategory: Ref

KBSubcategory: CodeSam BseFileio


INF: Consoles Do Not Support ANSI Escape Sequences

Article ID: Q84240

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Windows NT does not support ANSI escape sequences. There is some

functionality that this affects (for example, changing the color of the

prompt). This also affects a very limited number TTY-type programs that

rely on the console for escape support to be provided.

This feature is is under review and is being considered for future

releases.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCon


INF: Processes Maintain Only One Current Directory

Article ID: Q84244

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Processes under Windows NT maintain only one current directory. Under

MS-DOS or OS/2, a process will maintain a current directory for each drive.

MORE INFORMATION

================

For example, if you do the following

1. Set the current drive to be drive C and set the current directory

   to be \MAINC\MAINSUBC.

2. Change the current drive to be drive D and set the current

   directory to be \MAIND\MAINSUBD.

when you reset the current drive to drive C, the current directory will be

the original directory: \MAINC\MAINSUBC.

MS-DOS and OS/2 use a current directory structure (CDS) to maintain this

information. The memory for this structure is allocated at boot time, and

is set by the LASTDRIVE= line in the CONFIG.SYS file. For instance, if you

set LASTDRIVE=Z, you will have 26 entries in the CDS and will be able to

track 26 current directories.

Windows NT by default allows a process to track only one current directory-

-the one for the current drive--because the underlying operating system

does not use drive letters; it always uses fully-qualified names such as:

   \Device\HardDisk0\Partition1\autoexec.bat

The Win32 subsystem maintains drive letters by setting up symbolic links

such as:

   \DosDevices\C: == \Device\HardDisk0\Paritition1

   \DosDevices\D: == \Device\HardDisk0\Paritition2

   \DosDevices\E: == \Device\HardDisk1\Paritition1

(Partitions are 1-based while hard disks are 0-based because Partition0

refers to the entire physical device, which is the "file" that FDISK opens

to do its work.) Therefore, when you do SetCurrentDirectory("c:\tmp\sub"),

the Win32 subsystem translates that to "\DosDevices\c:\tmp\sub", "...".

As far as Windows NT is concerned, there are no "drives," there is one

object namespace.

CMD.EXE maintains a private current directory for each drive it has touched

and uses environment variables to associate a current directory with each

drive. These environment variables have the form "=<drive>:".

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


SAMPLE: CreateProcess() Priority Demonstration

Article ID: Q84539

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The sample STARTP demonstrates how to start a new process at a given

default priority. It is a functional replacement for the "start" command,

but with added features.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

STARTP starts a separate window to run a specified program. The following

is the command syntax for STARTP:

STARTP [/Ttitle] [/Dpath] [/h] [/l] [/min] [/max]

       [/c] [program] [parameters]

    title       Title to display in window title bar. Put entire

                parameter in quotation marks to include spaces in the

                title; for example, startp "/Ttest job".

    path        Starting directory.

    h           Set default to high priority.

    l           Set default to low priority.

    min         Start window minimized.

    max         Start window maximized.

    c           Use current console instead of creating a new console.

    program     A program to run as either a GUI application or a console

                application.

    parameters  These are the parameters passed to the program.

Note that the priority parameters may have no effect if the program changes

its own priority.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseProcThrd


SAMPLE: Security API Functions Demonstration

Article ID: Q85397

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The SIDCLN sample demonstrates some of the Win32 security API functions,

and provides a sample of how a utility could be written that recovers

on-disk resources remaining allocated to deleted user accounts.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The on-disk resources recovered are:

   Files that are still owned by accounts that have been

   deleted are assigned ownership to the account logged on

   when this sample is run.

   ACEs for deleted accounts are edited (deleted) out of

   the ACLs of files to which the deleted accounts had been

   granted authorizations (eg., Read access)

It may be that running this sample as a utility has no practical value in

many environments, as the number of files belonging to deleted user

accounts will often be quite small, and the number of bytes recovered on

disk by editing out ACEs for deleted accounts may well not be worth the

time it takes to run this sample. The time it takes to run this sample may

be quite significant when processing an entire hard disk or partition

NOTE:  This sample is not a supported utility.

TO RUN:

  You must log on using an account, such as Administrator,

  that has the priviledges to take file ownership and edit

  ACLs

  The ACL editing part of this sample can only be

  excercised for files on a partition that has ACLs NT

  processes:  NTFS

Typical test scenario:  Create a user account or two, log on as each of

these accounts in turn, while logged on for each account, go to an NTFS

partition, create a couple of files so the test accounts each own a few

files, use the file manager to edit permissions for those files so that

each test user has some authorities (e.g., Read) explicitly granted for

those files. Logon as Administrator, authorize each test user to a few

Administrator-owned files. Delete the test accounts. Run the sample in the

directories where you put the files the test accounts owned or were

authorized to.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMisc


SAMPLE: Creating Resource-Only DLLs

Article ID: Q85915

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The RESDLL sample shows how to create a resource-only dynamic link library

(DLL). In short, this is accomplished by creating and resource-compiling a

resource (.RC) file, then linking it without an entry point.

The MAIN.EXE program tests THE_DLL.DLL by loading it and referencing the

DLL's icon, cursor, and bitmap. The icon and cursor are used by the

registered window class, and the bitmap is used in painting the client

area.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseDll


SAMPLE: Demonstration of Setting File Attributes

Article ID: Q85917

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The SETINFO sample shows how to get and set information on file

date, time, attributes, and size. SETINFO demonstrates much of the

functionality of OS/2's DosQFileInfo() and DosSetFileInfo().

More specifically, the SETINFO sample shows how to set file attributes

and how to modify file and date times (and how to do the conversions

from file time to DosTime, and so on). To use the sample file, enter a

filename in the appropriate edit field and choose the Get Info.

button. To set file attributes or file date and time information,

modify the values in the edit fields and check buttons, and choose the

Set Info. and Set Attr. buttons. To slow down the return code

reporting, enter a larger value into the time edit field, and choose

the Set Time button.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseFileio


SAMPLE: Virtual Memory API Function Demonstration

Article ID: Q85919

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

VIRTMEM is a sample of the various virtual memory API functions

available under Win32.

When you start the application, you are initially given a RESERVED

page of virtual memory. You can change the protection and state of the

page through menu selections. Check marks will appear in the menu

items to indicate the current state and protection on the page. More

in-depth information regarding the page can be obtained by selecting

the Show Page menu item.

The Lock menu item allows you to lock and unlock the page in memory.

The application also uses structured exception handling and allows you

to try and write to the page in its various states and protections. To

do this, select the Test menu option.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMm


SAMPLE: Demonstration of Setting Console Text Color

Article ID: Q87329

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The CONSOLEC sample illustrates the use of the SetConsoleTextAttribute()

and GetConsoleScreenBufferInfo() functions to set the console text color

attributes.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

This sample also functions as a utility to set the text color of the

console window. The command syntax for the utility is as follows:

   COLOR FOREGROUND [BACKGROUND]

FOREGROUND and BACKGROUND are the new text color selections for the current

console. If the utility is invoked without any options, the utilities

syntax and a table of the possible color choices is displayed. The

BACKGROUND selection is optional, and thus just the FOREGROUND text color

can be changed.

Possible colors are: black, blue, green, cyan, red, magenta, yellow and

white. Each of these can be selected as the FOREGROUND or the BACKGROUND

color. Selection of the same color for both the FOREGROUND and the

BACKGROUND is not permitted. The color options are not case sensitive, and

only the first unique characters are necessary to select the color. For

example

   COLOR BLU W

will select blue on white text color attributes.

The text color attribute changes only affect new console output. Thus, text

in the console buffer before the utility is invoked retains its original

color attributes.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseCon


SAMPLE: Asynchronous I/O Demonstration

Article ID: Q87330

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The EVENT sample demonstrates performing asynchronous I/O in Win32. In

Win32 you can do this in two ways. One way is similar to OS/2 where a

thread is spawned that performs the I/O and returns. With Win32, when you

create a file, it signals to the system that you want to perform I/O

asynchronously. Then, when ReadFile(), for example, is going to take a

significant amount of time to complete, an ERROR_IO_PENDING error is

generated, signaling you to do other tasks until you NEED the data, at

which time you can use the GetOverlappedResults() function, which will

finish the I/O.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

Note that this activity has taken place without the need of an additional

thread to perform the work. This sample touches only on the capabilities of

what one can do with the new overlapped I/O functions. For example, an

application that uses pipes to communicate over the network to other

clients can create these file handles with the overlapped flag. Then,

instead of blocking and waiting for a connection, the server application

can go about doing useful tasks waiting for the pipe to enter the

"signaled" state. In addition, you can perform more than one operation on

this handle at one time, such as reading and writing to the same file.

All this power does not come without some responsibilities on the

programmer's side. First, the system does not keep track of the system file

pointers. In addition, you cannot use the data until the system responds by

setting an event to a signaled state.

In the first case this just means you need to keep track of the value

"lpNumberOfBytesTransfered" returned by GetOverlappedResult() and update

the OVERLAPPED structure with this information. This OVERLAPPED structure

will then be passed into the Read/WriteFile() function, which will use this

as the offset to the starting point for the I/O operation. The first call

to Read/WriteFile() will normally then have the offset fields in the

OVERLAPPED structure set to zero.

The second case should be used as a criteria of whether to use this type of

I/O. If you need the data before you can do anything else, use normal

synchronous I/O and let the system handle the details for you. This also

demonstrates an important reason for using an EVENT to wait on rather than

the file handle. While both are allowed in a multithread application, one

cannot guarantee that the thread that set the handle to the signaled state

will be the one returning from the GetOverlappedResult() because each

thread is using the same handle to wait on.

To keep this sample focused, the user interface is simple. To run this

sample at the command prompt, type:

   ASYNC_IO <In_file> <Out_file>

In_file and Out_file are place holders. As this is implemented, you cannot

write over an existing file. While this is up and running, you will see

vital statistics such as, such as the following:

 - When I/O is pending

 - How many bytes are transferred

 - End of file

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseSync


SAMPLE: Communications API Function Demonstration

Article ID: Q87331

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The COMM SDK sample application is designed to demonstrate the basics of

using the Win32 communications API functions while maintaining a common

code base with Win16 code.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The COMM program performs communications using the Windows functions

OpenFile(), ReadFile(), SetCommState(), SetCommMask(), WaitCommEvent(),

WriteFile(), and CloseFile().

This sample creates a background thread to watch for COMM receiver events

and posts a notification message to the main terminal window. Foreground

character processing is written to the communications port.

Simple TTY character translation is performed and a screen buffer is

implemented for use as the I/O window.

Overlapped file I/O techniques are demonstrated.

How to Use

----------

The baud rate, data bits, stop bits, parity, port, RTS/CTS handshaking,

DTR/DSR handshaking, and XON/XOFF handshaking can be changed under the

Settings menu item.

Once the communications settings are set up, the Action menu item can be

selected to connect or disconnect the TTY program.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseCommapi


SAMPLE: Demonstration of the Console API Functions

Article ID: Q87332

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The CONSOLE sample demonstrates the Win32 console API functions. The

program takes no parameters; to start, just run CONSOLE.EXE. After starting

the sample, you can click on one of the functions on the screen to get a

demonstration of that function. When viewing a demo of the function, the

title of the console window is changed to show the name of the source file

where that demo function resides. This should make it easy to find the

sample code where the function of interest resides.

Please note that some of the demos cover multiple APIs, so some of the menu

choices run the same demo.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseCon


INF: How HEAPSIZE/STACKSIZE Commit > Reserve Affects Execution

Article ID: Q89296

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The syntax for the module-definition statements HEAPSIZE and STACKSIZE is

as follows

   HEAPSIZE  [reserve] [,commit]

   STACKSIZE [reserve] [,commit]

The remarks for HEAPSIZE and STACKSIZE on page 62 of the "Tools User's

Guide" manual that comes with the Win32 SDK state the following:

   When commit is less than reserve, memory demands are reduced but

   execution time is slower.

By default, commit is less than reserve.

The reason that execution time is slower (and it is actually only

fractionally slower), is that the system sets up guard pages and could have

to process guard page faults.

MORE INFORMATION

================

If the committed memory is less than the reserved memory, the system sets

up guard page(s) around the heap or stack. When the heap or stack grows big

enough, the guard pages start accessing outside the committed area. This

causes a guard page fault, which tells the system to map in another page.

The application continues to run as if you had originally had the new page

committed.

If the committed memory is greater than the reserve, no guard pages are

created and the program faults if it goes outside the committed memory

area.

Experimenting with the commit versus reserve numbers may result in a

combination that would produce noticeable results, but for most

applications, this difference is probably not noticeable. The potential

benefits do not warrant significant experimentation.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Replacing the Windows NT Task Manager

Article ID: Q89373

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Under Windows 3.1, the Task Manager is an easily replaceable program.

However, under the Win32 subsystem of Windows NT, it is very difficult to

replace the Task Manager, due to special programming considerations. In

general, it is not recommended that users attempt this.

MORE INFORMATION

================

The Task Manager filename (TASKMAN.EXE) is stored in the registration

database under HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\

CurrentVersion\WinLogon\Shell. This name could be modified in order to

replace the Task Manager; however, as stated above, this is not

recommended.

Special requirements for the Task Manager make it very different from the

Windows 3.1 Task Manager. The EndTask button handling is done through

internal application programming interface (API) functions. These API

functions are not documented. The situation is the same for handling

foreground management, hung applications, and priority issues (to make sure

that the Task Manager will come up as fast as possible). In addition, the

Windows NT Task Manager uses shortcut ("hot") keys.

NOTE: The Task List has been incorporated into the Program Manager. To

remove the Task List you must also remove the Program Manager. The full

functionality of the Task List (as found in TASKMAN.EXE) is now folded into

the Program Manager (PROGMAN.EXE). If you completely delete the TASKMAN.EXE

file from your system and from the registry you will still be able to

invoke the Task List since it is built into the Program Manager. To

completely rid your system of the Task List you must not be running the

Program Manager.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: AllocConsole() Necessary to Get Valid Handles

Article ID: Q89750

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

If a graphical user interface (GUI) application redirects a standard

handle, such as stderr or stdout, and then spawns a child process, the

output of the child process will not be seen unless the AllocConsole()

application programming interface (API) is called before the standard

handle is redirected.

MORE INFORMATION

================

If an application spawns a child process without calling AllocConsole()

first, the child's console window will appear on the screen and the GUI

application will not be able to control this window (for example, it cannot

minimize the child window). In addition, users can terminate the child

process by choosing Close from the console window's Control (system) menu.

This causes users to think that only the window is closed, when in

actuality, the entire application is terminated. This can cause the user to

lose data in the console window.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCon


INF: How to Specify Shared and Nonshared Data in a DLL

Article ID: Q89817

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

To have both shared and nonshared data in a dynamic-link library (DLL)

which is built with a 32-bit Microsoft C compiler, you need to use the

#pragma data_seg directive to set up a new named section. You then must

specify the correct sharing attributes for this new named data section in

your .DEF file.

The system will try to load the shared memory block at the same address in

each process. However, if the block cannot be loaded into the same memory

address, the system allocates a new block of memory for that process and

the memory is not shared. No run time warnings are given when this happens,

therefore, named shared memory is generally a safer option.

MORE INFORMATION

================

Below is a sample of how to define a named data section in your DLL. The

first line directs the compiler to include all the data declared in this

section in the .MYSEC data segment. This means that the iSharedVar variable

would be considered part of the .MYSEC data segment. By default, data will

be nonshared.

Note that you must initialize all data in your named section. The data_seg

pragma only applies to initialized data.

The third line, "#pragma data_seg()", directs the compiler to reset

allocation to the default data section.

   #pragma data_seg(".MYSEC")

   int iSharedVar = 0;

   #pragma data_seg()

Below is a sample of the .DEF file that supports the shared and nonshared

segments. This definition will set the default section .MYSEC to be shared.

The default data section is by default non-shared, so any data not in

section .MYSEC will be non-shared.

   LIBRARY MyDll

   SECTIONS

     .MYSEC READ WRITE SHARED

   EXPORTS

    ...

NOTE: All section names must begin with a period character ('.') and

must not be longer than 8 characters, including the period character.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseDll


INF: Windows NT Servers in Locked Closets

Article ID: Q90083

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Some installations are required to restrict access to a server such that

access to the server's keyboard/mouse is unavailable to most personnel.

Such a server is referred to as a server in a locked closet.

The server administrators may provide an emergency reset button to end

users (for example, factory floor workers) in case the system locks up and

no administrators are present. In the case where an emergency reset button

cannot be provided, an administrator must come and physically unlock the

closet in order to get the system up again.

Windows NT requires that the user press CTRL+ALT+DEL to log on. This

requirement implies that Windows NT doesn't lend itself well to the server

in a locked closet situation. Indeed, someone must press CTRL+ALT+DEL and

enter a user ID and a password in order to log on and use the keyboard or

mouse to interact locally with a Windows NT machine. However, it is

possible to configure the machine as a server in a locked closet such that

an administrator is not required to unlock the door to reset the system.

The administrator can configure the system so that services are started

automatically during boot. Once all the services are started, then the

system is fully functional and the administrator need not intervene. If

certain services fail to come up, but network service does come up, then

the system can be remotely administered.

MORE INFORMATION

================

Remote administration is possible, assuming that the required basic system

services are running. The machine must be on the network. The process

requires only the Windows NT product. In other words, Windows NT Advanced

Server is not an additional requirement.

Make sure that the following steps have been taken to start system services

automatically at system boot and to enable remote administration in case of

failure:

1. Use the Service Control Manager to install any application code that

   must be started as soon as the Windows NT machine reboots.

   Write an application that installs the services and specifies that they

   should be started automatically. To find more information on the Win32

   APIs that support Services, search on "Services Overview" in the Win32

   API help text.

   Once this is done, the necessary application code can be made to start

   automatically upon system reboot, without anyone needing to press

   CTRL+ALT+DEL to log on or to take any other action using the server's

   local mouse/keyboard.

2. Make sure that the Workstation and Server services start automatically

   upon reboot.

   Use the Services application in Control Panel to ensure that both

   the Workstation and Server services start automatically upon

   reboot. Choose the Help button for instructions on how to install a

   service and how to configure it to start automatically.

   This will permit an authorized person to remotely administer the system

   from another machine on the network. Thus, if something from step 1 goes

   wrong, the administrator still does not need to physically unlock the

   closet and log on. The administrator can log on to any machine on the

   network and use the tools on that machine to interact with the server.

Remote administration via dial-up telephone lines is available, but

requires RAS (Microsoft Remote Access Service). RAS permits a machine to

dial over telephone lines into a network, and to become a full participant

on the network. In this way, a system dialing in over RAS can be used to

remotely administer the system in the locked closet.

Note that while these steps allow servers locked in closets to be restored

without an administrator, it is still preferable to install a UPS

(uninterruptable power supply). Servers in locked closets usually need to

provide uninterrupted service to their clients, so a UPS is a better

solution. The capability to do remote administration serves as a backup in

case of failure.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Apps Should Wait to Free/Re-use WriteFileEx's Buffer

Article ID: Q90087

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The WriteFileEx() function was introduced in the Win32 API. It is used to

write data to a file and report its completion asynchronously (a completion

routine is called when the write operation is complete). The following is

the function prototype, taken from the Programmer's Reference:

   BOOL WriteFileEx(hFile, lpBuffer, nNumberOfBytesToWrite,

         lpOverlapped, lpCompletionRoutine)

   HANDLE hFile;                             /* file to write */

   LPVOID lpBuffer;                          /* address of buffer */

   DWORD nNumberOfBytesToWrite;              /* bytes to write */

   LPOVERLAPPED lpOverlapped;                /* contains offset */

   LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine;

One point that the documentation does not stress is that the data buffer,

lpBuffer, should not be used by the application until the overlapped I/O

operation is completed. At that time, the operating system will let the

application know whether the buffer has been successfully written or

whether the data transfer failed. After the status is reported, the

application can free or re-use the buffer.

In general, we cannot assume that the operating system has its own copy of

the data in the buffer. The kernel can transfer directly from the buffer to

the device.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: CreateFile() Using CONOUT$ or CONIN$

Article ID: Q90088

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

If you attempt to open a console input or output handle by calling the

CreateFile() function with the special CONIN$ or CONOUT$ filenames, this

call will return INVALID_HANDLE_VALUE if you do not use the proper sharing

attributes for the fdwShareMode parameter in your CreateFile() call. Be

sure to use FILE_SHARE_READ when opening "CONIN$" and FILE_SHARE_WRITE when

opening "CONOUT$".

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: Cancelling Overlapped I/O

Article ID: Q90368

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

There is no routine in the Win32 API to cancel an asynchronous request once

it has been issued. When a thread does an overlapped I/O (that is, a

write), the system starts up another thread to do the I/O and leaves your

thread free to do other work. Once it is started, there is no way to stop

it.

If it necessary to interrupt the I/O, you can either

1. Split the writes into batches and check for interruptions. For example,

   you could break a 20 megabyte (MB) write into 20, 1 MB writes.

   -or-

2. Create another thread yourself to handle the I/O. Terminating the thread

   will cancel the I/O. You should have a thread in the process explicitly

   close the handle to the device.

   -or-

3. Close the handle to the device with the pending I/O. The close has the

    net effect of cancelling the I/O.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: Getting Real Handle to Thread/Process Requires Two Calls

Article ID: Q90470

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The API GetCurrentThread() returns a pseudo-handle rather than the real

handle to the thread. To get the real handle to the thread, you need to use

DuplicateHandle() using the pseudo-handle that is returned from

GetCurrentThread(). In addition, to get the real handle to a process, you

need to call DuplicateHandle() after calling GetCurrentProcess().

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseProcThrd


INF: Exporting Data from a DLL or an Application

Article ID: Q90530

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

It is possible for a Win32 application to be able to address DLL global

variables directly by name from within the executable. This is done by

exporting global data names in a way that is similar to the way you export

a DLL function name. Use the following steps to declare and utilize

exported global data.

1. Define the global variables in the DLL code. For example:

      int i = 1;

      int *j = 2;

      char *sz = "WBGLMCMTP";

2. Export the variables in the module-definition (DEF) file. Use of the

   CONSTANT keyword is required, as shown below:

   EXPORTS

      i  CONSTANT

      j  CONSTANT

      sz CONSTANT

3. Declare the variables in the modules that will use them (note that they

   must be declared as pointers because a pointer to the variable is

   exported, not the variable itself):

      extern int *i;

      extern int **j;

      extern char **sz;

4. Use the values by dereferencing the pointers declared in step 3:

      printf( "%d", *i );

      printf( "%d", **j );

      printf( "%s", *sz );

   It may simplify things to use #defines instead; then the variables can

   be used exactly as defined in the DLL:

      #define i *i

      #define j *j

      #define sz *sz

      extern int i;

      extern int *j;

      extern char *sz;

      printf( "%d", i );

      printf( "%d", *j );

      printf( "%s", sz );

MORE INFORMATION

================

NOTE: This technique can also be used to export a global variable from an

application so that it can be used in a DLL.

For more information on the use of EXPORTS and CONSTANT in the Module

Definition File (DEF) file, see Chapter 4 of the Win32 SDK "Tools" manual.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseDll


INF: Dynamic Loading of DLLs Under Windows NT

Article ID: Q90745

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

When using LoadLibrary() under Win16 or OS/2, the Dynamic Link Library

(DLL) is loaded only once. Therefore, the DLL has the same address in all

processes. Dynamic loading of DLLs is different under Windows NT.

A DLL is loaded separately for each process because each application has

its own address space, unlike Win16 and OS/2. Pages must be mapped into the

address space of a process. Therefore, it is possible that the DLL is

loaded at different addresses in different processes. The memory manager

optimizes the loading of DLLs so that if two processes share the same pages

from the same image, they will share the same physical memory.

Each DLL has a preferred base address, specified at link time. If the

address space from the base address to the base address plus image size is

unavailable, then the DLL is loaded elsewhere and fixups will be applied.

There is no way to specify a load address at load time.

To summarize, at load time the system:

1. Examines the image and determines its preferred base address and

   required size.

2. Finds the address space required and maps the image, copy-on-write,

   from the file.

3. Applies internal fixups if the image isn't at its preferred base.

4. Fixes up all dynamic link imports by placing the correct address for

   each imported function in the appropriate entry of the Import Address

   Table. This table is contiguous with 32-bit addresses, so 1024 imports

   require dirtying only one page.

MORE INFORMATION

================

The pages containing code are shared, using a copy-on-write scheme. The

term copy-on-write means that the pages are read-only; however, when a

process writes the page, instead of an access violation, the memory manager

makes a private copy of the page and allows the write to proceed. For

example, if two processes start from the same .EXE, both initially have all

pages mapped from the .EXE copy-on-write. As the two processes proceed to

modify pages, they get their own copies of the modified pages. The memory

manager is free to optimize unmodified pages and actually map the same

physical memory into the address space of both processes. Modified pages

are swapped to/from the page file instead of the .EXE file.

There are two kinds of fixups. One is the address of an imported function.

All these fixups are localized in what the Portable Executable (PE)

specification calls the Import Address Table (IAT). This is an array of 32-

bit function pointers, one for each imported API. The IAT is located on its

own page(s), because it is always modified. Calling an imported function is

actually an indirect call through the appropriate entry in this array. In

case that the image is loaded at the preferred address, the only fixups

needed are for imports.

Note that there is an optimization whereby each import library exports a 32-

bit number for each API along with any name and ordinal. This serves as a

"hint" to speed the fixups performed at load time. If the hints in the

program and the DLL do not match, the loader uses a binary search by name.

The other kind of fixup is needed for references to the image's own code or

data when the image can't be loaded at its preferred address. When a page

must be taken out of memory, the system checks to see whether the page has

been modified. If it has not, then the page is still mapped copy-on-write

against the EXE and can be discarded from memory. Otherwise, it must be

written to the page file before it can be removed from memory, so that the

page file is used as the backing store (where the page is recovered from)

rather than the executable image file.

NOTES

=====

The DLL's entry point does not get called for a second LoadLibrary() call

in a process (that is, no second DLL_PROCESS_ATTACH entry). There is one

call to DllEntry/DLL_THREAD_ATTACH per thread no matter the number of times

a thread calls LoadLibrary(). The same goes for FreeLibrary(), but the

DLL_PROCESS_DETACH happens only on the last call (that is, reference count

back to zero for the process).

Global instance data for the DLL is on a per process basis (only one set

per unique process). If it is necessary to ensure that global instance data

is unique for each LoadLibrary() performed in a single process, consider

thread local storage (TLS) as an alternative. This requires multiple

threads of execution, but TLS allows unique data for each ThreadID. There

is very little overhead on the DLL's part; just create a global TLS index

during process initialization. During thread initialization, allocate

memory (via HeapAlloc(), GlobalAlloc(), LocalAlloc(), malloc(), and so on)

and store a pointer to the memory using the global TLS index value in the

function TlsSetValue. Win32 internally stores each thread's pointer by TLS

index and ThreadID to achieve the thread specific storage.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseDll


INF: Implementing a "Kill" Operation in Windows NT

Article ID: Q90749

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The following sample demonstrates how to implement a "kill" operation, such

as a UNIX ps/kill, under Windows NT. Note that PView will give you the PID

you need.

The code sample makes use of the Win32 API TerminateProcess(). While

TerminateProcess() does clean up the objects owned by the process, it does

not notify any DLLs hooked to the process. Therefore, one can easily leave

the DLL in an unstable state.

In general, the Task List is a much cleaner method of killing processes.

MORE INFORMATION

================

The following sample shows how to "kill" a process, given its process ID

(PID).

Sample Code

-----------

#include <stdio.h>

#include <stdlib.h>

#include <stdarg.h>

#include <windows.h>

#include <string.h>

#include <math.h>

#include <winbase.h>

void ErrorOut(char errstring[30])

/*

Purpose: Print out an meaningful error code by means of

         GetLastError and printf.

Inputs:  errstring - the action that failed, passed by the

                     calling proc.

Returns: none

Calls:   GetLastError

*/

{

   DWORD Error;

   Error= GetLastError();

   printf("Error on %s = %d\n", errstring, Error);

}

void main(int argc, char *argv[])

{

   HANDLE hProcess;

   DWORD ProcId;

   BOOL TermSucc;

   if (argc == 2)

   {

      sscanf(agrv[1],"%x",ProcId);

      hProcess= OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcId);

      if (hProcess == NULL)

         ErrorOut("OpenProcess");

      TermSucc= TerminateProcess(hProcess, 0);

      if (TermSucc == FALSE)

         ErrorOut("TerminateProcess");

      else

         printf("Process# %.0lf terminated successfully!\n", ProcId);

   }

   else

   {

      printf("\nKills an active Process\n");

      printf("Usage: killproc ProcessID\n");

   }

}

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseProcThrd


INF: Default Attributes for Console Windows

Article ID: Q90837

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Console attributes (screen fonts, screen colors, insert/overstrike, etc.)

are stored by console title within each user's profile. When a profile for

a new window is not found, the .DEFAULT configuration is used.

MORE INFORMATION

================

You can change the start font, screen colors, pop up colors, and

insert/overstrike defaults using REGEDT32. Under the key HKEY_USERS, there

is a .DEFAULT along with an entry for each user who has an account on that

machine. Select DEFAULT\Console\Configuration. Use Edit.AddValue to add

FontSize as a REG_DWORD to change the default font, Add ScreenColors and

PopupColors as REG_DWORDs to change those defaults. To reset the console to

be in insert mode rather than overstrike mode, add InsertMode as REG_SZ and

set it to ON.

To get the right settings for the font size and colors you should first set

your MS-DOS Prompt window font size and colors. Look up Console\MS-DOS

Prompt\Configuration under your account and write down the values for the

keys you need to add. Then go back to DEFAULT\Console\Configuration and add

those values.

The DEFAULT configuration is read when the user chooses the Command

prompt. However, if the user chooses to run a command shell via the

File Manager (selecting CMD.EXE and choosing Run from the File menu),

the DEFAULT configuration will not be read out of the registry.

-----------------------------------------------------------------------

WARNING:

RegEdit is a very powerful utility that facilitates directly changing

the Registry Database. Using RegEdit incorrectly can cause serious

problems, including hard disk corruption. It may be necessary to

reinstall the software to correct some problems. Microsoft does not

support changes made with RegEdit. Use this tool at your own risk.

-----------------------------------------------------------------------

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCon


INF: Win32 Priority Class Mechanism and the START Command

Article ID: Q90910

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The Win32 priority class mechanism is exposed through CMD.EXE's START

command.

START accepts the following switches:

   /LOW        -  Start the command in the idle priority class.

   /NORMAL     -  Start the command in the normal priority class

                  (this is the default).

   /HIGH       -  Start the command in the high priority class.

   /REALTIME   -  Start the command in the real-time priority class.

For a complete list of START switches, type the following command at

the Windows NT command prompt:

   start /?

Win32 has also been modified to inherit priority class if the parent's

priority class is idle; thus, a command such as

   start /LOW nmake

causes build and all descendants (compiles, links, and so on) to run in the

idle priority class. Use this method to do a real background build that

will not interfere with anything else on your system.

A command such as

   start /HIGH nmake

runs BUILD.EXE in the high priority class, but all descendants run in the

normal priority class.

MORE INFORMATION

================

Be very careful with START /HIGH and START /REALTIME. If you use either of

these switches to start applications that require a lot of cycles, the

applications will get all the cycles they ask for, which may cause the

system to appear hung.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseProcThrd


PRB: SEH with Abort() in the try Body

Article ID: Q91146

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

When using Structured Exception Handling, if the try body calls abort(),

the finally body is not executed.

CAUSE

=====

The finally body is not executed because the abort() never returns. It

calls ExitProcess(), which terminates the process.

RESOLUTION

==========

This behavior is by design.

Additional reference words: 3.10

KBCategory: Prog

KBSubcategory: BseExcept


PRB: SEH with return in the finally Body Preempts Unwind

Article ID: Q91147

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

When using Structured Exception Handling (SEH), returning out of a finally

body results in a return from the containing procedure scope. For instance,

in the following code fragment, the return in the finally block results in

a return from func():

   int func()

   {

       int status = 0;

       __try {

          ...

          status = test();

          ...

       }

       __finally {

          if (status != 0) {

             status = FAILURE;

             return status;

          }

       }

       return status;

   }

CAUSE

=====

A return from within a __finally is equivalent to a goto to the closing

brace in the enclosing function [for example, func()]. This is allowed,

but has consequences that should normally be avoided.

Exception handling has two stages. First, the exception stack is walked,

looking for an accepting __except. When an accepting handler has been

found, all __finallys between the top-of-exception-stack and the target

__except will be called. During this "unwind", the __finallys are

assumed to each execute and then return to their caller (the system

unwind code).

A return in a finally abnormally aborts this unwinding. Instead of

returning to the system unwinder, the __finally returns to the enclosing

function's caller [for example, func()'s parent]. The accepting __except

filter may set some status or perform an allocation in anticipation of

the __except handler being entered. In this case, the intervening

__finally with the return will stop the unwind, and the __except handler

is never entered.

RESOLUTION

==========

This is by design. It makes it possible for a finally handler to stop an

unwind and return a status. This is what is referred to as a collided

unwind.

Abnormal termination from try/except or try/finally blocks is not

generally recommended because it is a performance hit.

The example can be rewritten so that the unwind chain is not aborted:

   int func()

   {

      int status = 0;

      __try {

         ...

         status = test();

         ...

      }

      __except(status != 0) {

          /* null */

      }

      if (status != 0)

         status = FAILURE;

      return status;

   }

This does not have identical semantics because the exception filters

higher up the exception stack will not be executed. However, ensuring

that both phases of exception handling progress to the same depth is a

more robust solution.

MORE INFORMATION

================

Normally this behavior is transparent to any higher-level exception

handling code. If, however, a filter function, as a side effect, stores

information that it expects to process in an exception handler, then it may

or may not be transparent. Storing such information in a filter function

should be avoided because it is always possible that the exception handler

will not be executed because the unwind is preempted. In the absence of

storing such side effects, it will be transparent that an exception

occurred and an attempted unwind occurred if one of the descendent

functions has a try/finally block with an finally clause that preempts the

unwind.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseExcept


INF: Initiating an Unwind in an Exception Handler

Article ID: Q91148

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

In the "Structured Exception Handling" overview in the "Win32 Programmer's

Reference", the last paragraph of the Exception Handling and Unwind

subsection says that "the exception handler usually initiates an unwind

operation by calling a system supplied function".

The paragraph describes what the compiler-generated code for try-except

does. Initiating the unwind is automatically handled by the compiler when

you exit the handler in any way other than by sequentially executing the

final statement, for example, with a goto, return, break, and so forth. See

the example below.

Because exception handling can be quite different under different processor

architectures, the description uses words such as "usually"; "usually" you

initiate an unwind. In some cases (for example, a goto to a label in the

current call frame), you don't need to unwind (you already did when you hit

the handler), so none is needed, and the compiler need not bother calling

the system to do one.

Note that unwinds aren't a fast operation. It would generally be better for

the exception filter to decide the exception can't be handled, and evaluate

to EXCEPTION_CONTINUE_SEARCH, than to force the unwind this way. If some

cleanup still needs doing, the termination handler will be called during

the unwind operation and could do the cleanup.

MORE INFORMATION

================

The following code fragment demonstrates initiating an unwind by exiting

the exception handler with a goto statement:

   int func() {

      try {

         ThisCode( BuggyParameter );

      }

      except( EXCEPTION_EXECUTE_HANDLER ) {

         if( ICannotContinue( BuggyParameter ) )

             goto InitUnwind;  //  <- This initiates the desired unwind

         HandleProblemBrilliantly( BuggyParameter );

      }

   InitUnwind:

      ProcessData();

      IssueError();

      RetireGracefully();

   }

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseExcept


INF: Using volatile to Prevent Optimization of try/except

Article ID: Q91149

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The following is an example of a valid optimization that may take

programmers by surprise.

1. A variable (temp) used only within the try-except body is declared

   outside it, and therefore is global with respect to the try.

2. Assignment to the variable (temp) is in the program only for a possible

   side effect of doing a read memory access through the pointer.

MORE INFORMATION

================

For example:

   VOID

   puRoutine( PULONG pu )

   {

      ...

      ULONG temp;       // Just for probing

      ...

      try {

         temp = *pu;    // See if pu is a valid argument

      }

      except {

         // Handle exception

      }

   }

The compiler optimizes and eliminates the entire try-except statement

because temp is not used later.

If the value of temp were used globally, the compiler should treat the

assignment to temp as volatile and do the assignment immediately even if it

is overwritten later in the body of the try. The reasoning is that, at

almost any point in the try body, control may jump to the except (or an

exception filter). Presumably the programmer accessing the variable outside

the try wants to get the current (most recently assigned) value.

The way to prevent the compiler from performing the optimization is:

   temp = (volatile ULONG) *pu;

If a temporary variable is not needed, given the example, the read access

should still be specified as volatile, for example:

   *(volatile PULONG) pu;

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseExcept


INF: Icons for Console Applications

Article ID: Q91150

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Under OS/2, when adding an application named CONAPP.EXE to a program group,

the system uses the file CONAPP.ICO (if it exists ) as the icon. This does

not happen automatically under Windows NT; the item will have a generic

icon.

To specify the icon that appears in the program group, use the following

steps:

1. Create a resource file containing an ICON statement:

      ConApp ICON ConApp.ICO

2. Compile the resource using RC:

      rc -r $(rcvars) -fo conapp.res conapp.rc

3. Add the .rc file to the link command line

MORE INFORMATION

================

If the application is started by clicking its icon in Program Manager, the

icon that appears when the application is minimized will be that icon,

whether it is a generic icon or an icon imbedded in the executable file.

If the application is started from the MS-DOS prompt or the File menu, then

the icon that appears when the application is minimized will be the icon

that is used for the MS-DOS prompt.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCon


INF: Memory Handle Allocation

Article ID: Q91194

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

This article discusses the limitations that exist when allocating memory

handles.

The minimum block you can reserve with each call to VirtualAlloc() is 64K.

It is a good idea to confirm this number by checking the allocation

granularity returned by GetSystemInfo().

With HeapAlloc(), there is no limit to the number of handles that can be

allocated. GlobalAlloc() and LocalAlloc() (combined) are limited to 65536

total handles for GMEM_MOVEABLE and LMEM_MOVEABLE memory per process. Note

that this limitation does not apply to GMEM_FIXED or LMEM_FIXED memory.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMm


DOCERR: Return Values of Performance APIs

Article ID: Q91215

----------------------------------------------------------------------

The information in this article applies to:

 - Beta Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

In the Win32 API documentation, the APIs QueryPerformanceCounter() and

QueryPerformanceFrequency() are incorrectly documented as returning FALSE

when a high performance timer is not present and TRUE when a high

performance timer is present.

The reverse is correct; FALSE (SUCCESS) is returned when a high performance

counter is present in the system and TRUE (!SUCCESS) is returned when a

high performance counter is not present.

For x86 and R4000 systems, FALSE (SUCCESS) is always returned because high

performance counters are available on both platforms.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Sharing Win32 Services

Article ID: Q91698

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Win32 services are discussed in the overview for the Service Control

Manager. The documentation says that:

   A Win32 service runs in a Win32 process which it may or may not share

   with other Win32 services.

Whether or not a service has its own process is determined by which of

these service types is specified in the call to CreateService() to add the

service to the Service Control Manager Database.

SERVICE_WIN32_OWN_PROCESS

   This service type indicates that only one service can run in the

   process. This allows an application to spawn multiple copies of a

   service under different names, each of which gets its own process. This

   is the most common type of service.

SERVICE_WIN32_SHARE_PROCESS

   This service type indicates that more than one service can be run in a

   single process. When the second service is started, it is started as a

   thread in the existing process. A new process is not created. An example

   of this is the LAN Manage Workstation and the LAN Manager Server. Note

   that the service must be started in the system account, which is

   .\System. The name must be NULL.

The service type for each service is stored in the registry. The values are

as follows:

   SERVICE_WIN32_OWN_PROCESS    0x10

   SERVICE_WIN32_SHARE_PROCESS  0x20.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseService


INF: Determining Whether Windows NT Is Running

Article ID: Q92395

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Programmers can use GetVersion() to determine what version of Windows their

applications are running under. This might be a version of MS-DOS/Windows,

Windows on Windows (WOW), MS-DOS/Windows using extensions (Win32s), Windows

NT, or Windows NT Advanced Server. According to the documentation, the

return value of GetVersion() is a DWORD that specifies the major and minor

version numbers.

MORE INFORMATION

================

The following table shows the return values from GetVersion() under various

environments:

+-----------------------------------------------------------------+

|  Environment  |  LOWORD                 | HIWORD                |

+=================================================================+

|  Win16 on     |  Windows version        | MS-DOS version        |

|  Windows 3.x  |                         |                       |

+-----------------------------------------------------------------+

|  Win16 on WOW |  Windows version 3.1    | MS-DOS version 5.0    |

+-----------------------------------------------------------------+

|  Win32s on    |  Windows version 3.1    | RESERVED *            |

|  Windows 3.x  |                         |                       |

+-----------------------------------------------------------------+

|  Win32 on     |  Windows version 3.1    | RESERVED **           |

|  Windows NT   |                         |                       |

+-----------------------------------------------------------------+

 * The highest bit is 1. Note that the version of MS-DOS cannot be

   determined as it can under Windows 3.x.

** The highest bit is 0. The remaining bits specify build number.

NOTE: Windows 3.1 and WOW can return the same results. Therefore,

GetVersion() is especially useful only for 32-bit applications to determine

whether they are running under Windows NT or under Windows 3.1 with Win32s.

This is done by masking off the high bit.

Therefore, 16-bit applications should use GetWinFlags() to determine

whether they are being run under MS-DOS/Windows or WOW. GetWinFlags()

returns a WF_WINNT flag if the application is running under WOW.

GetWinFlags() is an existing function that has had the following flag

added in WOW:

   #define WF_WINNT         0x4000

GetWinFlags() is not a part of the Win32 API. Processor information can be

found through the new Win32 API GetSystemInfo().

In order to distinguish between Windows NT and Windows NT Advanced Server,

use the registry API to query the following:

   \HKEY_LOCAL_MACHINE\SYSTEM

   \CurrentControlSet

   \Control

   \ProductOptions

The result will be either WINNT or LANMANNT (for NTAS).

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Process Will Not Terminate Unless System Is In User-mode

Article ID: Q92761

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Under Windows NT, a process will not be terminated unless the system is

in user-mode. Suppose that TerminateProcess() is called while a device

driver or filesystem code is being executed. The system will wait until

the threads are running user code before marking the process for

termination. On system exit, processes that were the target of a

TerminateProcess() will be killed.

This may affect drivers. If a driver is waiting for an object or

multiple objects in WaitMode or UserMode, its wait may complete

unsuccessfully due to a termination request. Any code that does a

UserMode wait or an Alertable wait must check the return status of the

wait call. If the wait fails with STATUS_USER_APC or STATUS_ALERTED,

this is not an error. The driver should cleanup and return to user-mode.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseProcThrd


INF: Non-Addressable Range in Address Space

Article ID: Q92764

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

In Windows NT, each process has its own private address space. The process

can use up to 2 gigabytes of virtual memory. This 2Gb is not necessarily

contiguous. The system uses the other 2Gb.

The user-mode addresses extend from 0x00010000 to 0x7FFF0000. The

following ranges are reserved as non-address space to ensure that the

process does not walk on system-owned memory

   0x00000000 to 0x0000FFFF    (first 64K of virtual space)

   0x7FFF0000 to 0x7FFFFFFF    (last 64K of user virtual space)

These are effectively PAGE_NOACCESS ranges.

Additionally, Win32 DLLs will reserve other specific address ranges. For

more information, see the file COFFBASE.TXT that comes with the DDK.

MORE INFORMATION

================

This range is not guaranteed to serve this purpose in the future. There

could be good reasons in a future implementation to use these addresses.

Code that is going to depend on this non-address range should verify its

validity at run time with something like

   BOOL IsFirst64kInvalid(void)

   {

      BOOL bFirst64kInvalid = FALSE;

      try {

         *(char *)0x0000FFFF;

      }

      except (EXCEPTION_EXECUTE_HANDLER) {

         if (EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())

            bFirst64kInvalid = TRUE;

      }

      return bFirst64kInvalid;

   }

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMm


INF: Alternatives to Using GetProcAddress() With LoadLibrary()

Article ID: Q92862

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

When loading a DLL with LoadLibrary(), an alternative to calling

GetProcAddress() for each of your DLL entry points is to have the DLL

initialization function initialize a global structure or array containing

the addresses of these DLL entry points, then call a DLL function from your

executable which will return the address of this structure or array to your

executable. You can then call your DLL functions via the function pointers

in this structure or array.

MORE INFORMATION

================

The best place to initialize this structure or array of function pointers

would be in the DLL_PROCESS_ATTACH code of your DLL's main entry point. The

structure or array containing these function pointers must be declared as

either a global variable or as dynamically allocated memory (malloc(),

GlobalAlloc(), etc.) in your DLL in order for the executable to be able to

address this memory properly.

It is also possible, though not as clean, to export the global structure or

array of function pointers so that your executable can use the structure or

array by name directly in your executable. For more information on how to

declare and export global data in a Win32 DLL, please see the following

article(s) in the Microsoft Knowledge Base:

   ARTICLE-ID: Q90530

   TITLE     : INF: Exporting Data From a DLL

Be careful not to call these DLL functions via the function pointers after

the DLL is unloaded via FreeLibrary(). After FreeLibrary() is called, these

function pointer addresses are invalid and calling them will result in an

access violation.

This technique of returning pointers to DLL entry points is a supported

technique and will work on all hardware platforms that Windows NT supports.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseDll


INF: Secure Erasure Under Windows NT

Article ID: Q94239

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

File systems under Windows NT currently have virtual secure erasure (when a

file is deleted, the data is no longer accessible through the operating

system). Although the bits could still be on disk, Windows NT will not

allow access to them.

MORE INFORMATION

================

The NTFS file system does this by keeping a high-water mark, for each file,

of bytes written to the file. Everything below the line is real data,

anything above the line is (on disk) random garbage that used to be free

space, but any attempt to read past this high-water mark returns all zeros.

Other reusable objects are also protected. For example, all the memory

pages in a process's address space are zeroed when they are touched (unlike

the file system, a process may directly access its pages, and thus the

pages must be actually zeroed rather than virtually zeroed).

Note that file system security assumes physical security; in other words,

if a person has physical access to a machine and can boot an alternative

operating system and/or add custom device drivers and programs, he/she can

always get direct access to the bits on disk.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: WM_COMMNOTIFY is Obsolete for Win32 Applications

Article ID: Q94561

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Under Windows version 3.1, the WM_COMMNOTIFY message is posted by a

communication device driver whenever a COM port event occurs. The message

indicates the status of a window's input or output queue.

This message is currently not supported for Win32 applications running

under Windows NT. However, WOW supports the EnableCommNotification() API

for Win16 applications running on Windows NT.

MORE INFORMATION

================

To duplicate the Windows 3.1 functionality for a Win32 application running

under Windows NT, refer to the TTY sample, included with the SDK. The TTY

sample is a common code base sample, which uses EnableCommNotification()

under Windows 3.1 to tell COMM.DRV to post messages to the TTY window.

Under Windows NT, this behavior is simulated with a secondary thread which

uses WaitCommEvent() to block on the port and PostMessage() to indicate

when the desired event has occurred.

TTY.C defines WM_COMMNOTIFY if WIN32 is defined. Using this method,

WM_COMMNOTIFY notifications are simulated but use the same message

definition as Windows 3.1.

The TTY sample is located on the Win32 SDK CD in \MSTOOLS\SAMPLES\COMM.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCommapi


INF: Thread Local Storage Overview

Article ID: Q94804

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Thread local storage (TLS) is a method by which each thread in a given

process is given a location(s) in which to store thread-specific data.

Four functions exist for TLS: TlsAlloc(), TlsGetValue(), TlsSetValue(), and

TlsFree(). These functions manipulate TLS indexes, which refer to storage

areas for each thread in a process. A given index is valid only within the

process that allocated it.

Note that the Visual C++ compiler supports an alternate syntax:

   _declspec( thread )

which can be used in place of directly calling these APIs. Please see the

description of _declspec in the VC++ "Language and Run-time Help" helpfile

for more information.

MORE INFORMATION

================

A call to TlsAlloc() returns a global TLS index. This one TLS index is

valid for every thread within the process that allocated it, and should

therefore be saved in a global or static variable.

Thread local storage works as follows: when TlsAlloc() is called, every

thread within the process has its own private DWORD-sized space reserved

for it (in its stack space, but this is implementation-specific). However,

only one TLS index is returned. This single TLS index may be used by each

and every thread in the process to refer to the unique space that

TlsAlloc() reserved for it.

For this reason, TlsAlloc() is often called only once. This is convenient

for DLLs, which can distinguish between DLL_PROCESS_ATTACH (where the first

process's thread is connecting to the DLL) and DLL_THREAD_ATTACH

(subsequent threads of that process are attaching). For instance, the first

thread calls TlsAlloc() and stores the TLS index in a global or static

variable, and every other thread that attaches to the DLL refers to the

global variable to access their local storage space.

Although one TLS index is usually sufficient, a process may have up to

TLS_MINIMUM_AVAILABLE indexes (guaranteed to be greater than or equal

to 64).

Once a TLS index has been allocated (and stored), the threads within the

process may use it to set and retrieve values in their storage spaces. A

thread may store any DWORD-sized value in its local storage (for example, a

DWORD value, a pointer to some dynamically allocated memory, and so forth).

The TlsSetValue() and TlsGetValue() APIs are used for this purpose.

A process should free TLS indexes with TlsFree() when it has finished using

them. However, if any threads in the process have stored a pointer to

dynamically allocated memory within their local storage spaces, it is

important to free the memory or retrieve the pointer to it before freeing

the TLS index, or it will be lost.

For more information, please see "Using Thread Local Storage" in the

"Processes and Threads" overview in the "Win32 Programmer's Reference".

Example

-------

Thread A within a process calls TlsAlloc(), and stores the index returned

in the global variable TlsIndex:

   TlsIndex = TlsAlloc();

Thread A then allocates 100 bytes of dynamic memory, and stores it in its

local storage:

   TlsSetValue( TlsIndex, malloc(100) );

Thread A creates thread B, which stores a handle to a window in its local

storage space referred to by TlsIndex.

   TlsSetValue( TlsIndex, (LPVOID)hSomeWindow );

Note that TlsIndex refers to a different location when thread B uses it,

than when thread A uses it. Each thread has its own location referred to by

the same value in TlsIndex.

Thread B may terminate safely because it does not need to specifically free

the value in its local storage.

Before thread A terminates, however, it must first free the dynamically

allocated memory in its local storage

   free( TlsGetValue( TlsIndex ) );

and then free the TLS index:

   if ( !TlsFree( TlsIndex ) )

      // TlsFree() failed.  Handle error.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseProcThrd


INF: Precautions When Passing Security Attributes

Article ID: Q94839

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

All Win32 APIs that allow security to be specified take a parameter of type

LPSECURITY_ATTRIBUTES as the means to attach the security descriptor.

However, it is a common error to pass a PSECURITY_DESCRIPTOR type to such

functions instead. Because PSECURITY_DESCRIPTOR is of type LPVOID (for

opaque data-type reasons), by C Language definition, it is implicitly

converted to the correct type. Therefore, the compiler does not generate

any warnings; however, unexpected run-time errors will result.

MORE INFORMATION

================

Below is a correct example of creating a named pipe with a security

descriptor attached.

Sample Code

-----------

   saSecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);

   saSecurityAttributes.lpSecurityDescriptor = psdAbsoluteSD;

   saSecurityAttributes.bInheritHandle = FALSE;

   hPipe = CreateNamedPipe(TEST_PIPE_NAME,

                           PIPE_ACCESS_DUPLEX,

   (PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_WAIT),

                           100,  // maximum instances

                           0,    // output buffer, sized as needed

                           0,    // input buffer, sized as needed

                           100,  // timeout in milliseconds

   (LPSECURITY_ATTRIBUTES)&saSecurityAttributes);

   if( INVALID_HANDLE_VALUE == hPipe )

   { // handle error

   }

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Physical Memory Limits Number of Processes/Threads

Article ID: Q94840

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Each time Windows NT creates an object, such as a process or a thread, it

must allocate a certain amount of physical memory (nonpaged pool) for its

support. The amount of memory that is needed for support of a thread object

is significantly higher than the memory requirement for support of a

process object. The amount of memory that is required for a thread object

on a RISC machine is also significantly higher than the memory requirement

for a thread on an x86 machine, due to the greater number and size of

registers on the RISC machines.

Due to the physical memory requirement of processes and threads, programs

that use the CreateProcess() and CreateThread() APIs should be careful to

check their return codes to detect out-of-memory conditions.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseProcThrd


SAMPLE: File I/O API Functions Demonstration

Article ID: Q94905

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

FILER is a basic file management applet, ala File Manager or Norton

CommanderTM. It demonstrates many of the new File I/O API, and their

related algorithms, such as drive enumeration, .EXE Version Information

retrieval and directory tree expansion. It also demonstrates many intensive

user algorithms, such as child managment, subclassing, synchronization and

control window management.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

FILER presents the user with two configurable child windows, each of

which the user may associate with a drive from the drives available on

the system.

A Drive Toolbar describes the available drives on the system. Users select

drives from the toolbar or the Drives menu. A function toolbar also

corresponds to the file I/O functions in the File menu. A command line

window at the bottom of the app will spawn a command shell with the command

given, and the option of keeping or destroying the command window after the

given command completes.

Each of these Drive child windows contains a Directory ListBox, and a

File ListBox, with which the user may browse through the files on the

selected drive.

FILER gives the user the option to Open (execute/edit), Copy, Delete, Move,

and Rename files, as well as Make and Remove Directories, and display

version information embedded in Win32 files. The active Drive child acts as

the source, and the inactive Drive child acts as the default destination of

file I/O operations.

The Drive children may also be configured as side by side or above

and below one another, and the File and Directory Listboxes in each

may swap positions. The user may opt to fully expand the Directory trees.

All features of FILER may be selected from the Mouse, Keyboard, or by Menu

Items.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseFileio


INF: Calculating String Length in Registry

Article ID: Q94920

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

When writing a string to the registry, you must specify the length of the

string, including the terminating null character (\0). A common error is to

use strlen() to determine the length of the string, but to forget that

strlen() returns only the number of characters in the string, not including

the null terminator.

Therefore, the length of the string should be calculated as:

   strlen( string ) + 1

Note that a REG_MULTI_SZ string, which contains multiple null-terminated

strings, ends with two (2) null characters, which must be factored into the

length of the string. For example, a REG_MULTI_SZ string might resemble the

following in memory:

   string1\0string2\0string3\0laststring\0\0

When calculating the length of a REG_MULTI_SZ string, add the length of

each of the component strings, as above, and add one for the final

terminating null.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: PAGE_READONLY May Be Used as Discardable Memory

Article ID: Q94947

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Virtual memory pages marked as PAGE_READONLY under Win32 may be used the

way discardable segments of memory are used in Windows 3.1. These virtual

memory pages are by default not "dirty," so the system may use them

(zeroing them first if necessary) without having to first write their

contents to disk.

From a system resource perspective, PAGE_READONLY is treated similar to

discardable memory under Windows 3.1 when the system needs to free up

resources. From a programming standpoint, the system automatically re-reads

the memory when the data is next accessed (for example, we attempt to

access our page when it has been "discarded," a page fault is generated,

and the system reads it back in). Memory-mapped files are convenient for

setting up this type of behavior.

If a PAGE_READONLY memory page becomes dirty [by changing the protection

via VirtualProtect() to PAGE_READWRITE, changing the data, and restoring

PAGE_READONLY], the page will be written to disk before the system uses it.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMm


INF: Clarification of COMMPROP dwMax?xQueue Members

Article ID: Q94950

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The entry for the COMMPROP structure in the Win32 Programmer's Reference

states that for the dwMaxTxQueue and dwMaxRxQueue members, "a value of 0

means that this field is not used".

MORE INFORMATION

================

This statement means that the provider does not restrict you to maximum Rx

and Tx queue values, and these members [returned by GetCommProperties()]

should not be used to determine the size of your transmit and receive

buffers when calling SetupComm().

Based on the memory present in the system, the Windows NT serial driver

determines a default Rx queue size (currently 128 bytes on low memory

systems and 4K on high memory systems). The current Rx and Tx queue sizes

are located in the dwCurrentTxQueue and dwCurrentRxQueue members.

SetupComm() allows you to change these default queue sizes. However, you

should not assume that the given serial driver will allocate any memory.

The queue size allocated is stored in the dwCurrentRxQueue member of the

COMMPROP structure. You may use this information to set the XonLim and

XoffLim members of the device control block (DCB) structure.

The Microsoft-supplied serial driver attempts to allocate at least the

amount requested for the RXQUEUE and, failing this, the request will also

fail. The driver never attempts to allocate memory for the TXQUEUE.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCommapi


INF: OpenComm() and Related Flags Obsolete Under Win32

Article ID: Q94990

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

OpenComm(), a Windows 3.1 application programming interface (API), is

obsolete under Windows NT and is not in the Win32 API. Note that the flags,

IE_BADID, IE_BAUDRATE, IE_BYTESIZE, IE_DEFAULT, IE_HARDWARE, IE_MEMORY,

IE_NOPEN, and IE_OPEN are obsolete, but are still in the header files.

OpenComm() is provided for Win16 applications running under Windows on

Win32 (WOW).

MORE INFORMATION

================

Under Win32, CreateFile() is used to create a handle to a communications

resource (for example, COM1). The fdwShareMode parameter must be 0

(exclusive access), the fdwCreate parameter must be OPEN_EXISTING, and the

hTemplate parameter must be NULL. Read, write, or read/write access can be

specified and the handle can be opened for overlapped I/O.

ReadFile() and WriteFile() are used for communciations I/O. The TTY sample

program shipped with the Win32 Software Development Kit (SDK) demonstrates

how to do serial I/O under Windows NT.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCommapi


INF: Global Quota for Registry Data

Article ID: Q94993

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Window NT includes a "global quota" on the amount of memory that may be

allocated in the registry. This prevents a broken or malicious application

from effectively crashing the system by filling paged pool with registry

data; however, it does NOT prevent such an application from using up all

available registry space. Similar to the file systems, the registry does

not support per process/user quotas.

MORE INFORMATION

================

The total amount of memory that may be consumed by registry data (the

hives) is limited by the registry size limit (RSL). The RSL works as a

"global quota" for registry space, both in the paged pool and on disk.

By default, the RSL is 25 percent of the size of the paged pool (the paged

pool is the memory that may be swapped to disk; all user memory is part of

the paged pool). Changing the size of the paged pool also affects the size

of the RSL. See

   HKEY_LOCAL_MACHINE\System\

      CurrentControlSet\

      Control\

      SessionManager\

      MemoryManagement\

      PagedPoolSize

in the registry.

The RSL may also be manually set. The value in bytes may be specified

by setting the value entry for the key

   HKEY_LOCAL_MACHINE\System\

      CurrentControlSet\

      Control\

      RegistrySizeLimit.

This key must have a type of REG_DWORD and a data length of 4 bytes, or it

will be ignored.

If the value entry RegistrySizeLimit is less than 4 megabytes (MB), it will

be forced up to 4 MB. If it is greater than about 80 percent of the size of

the paged pool, it will be set down to 80 percent of the size of the paged

pool. (It is assumed that paged pool is always larger than 5 MB.)

The system must be rebooted for changes in the RSL to take effect.

To ensure that the user can always at least boot and edit the registry if

they somehow set the RSL wrong, the quota is not enforced until after the

first successful loading of a hive (that is, loading of a user profile.)

Note that the RSL sets a maximum, not an allocation (unlike some other such

limits in the system). Setting a large RSL does NOT cause the system to set

aside that much space unless it is actually needed by the registry. It also

does NOT guarantee that that much space will be available for use in the

registry.

Setting the value entry RegistrySizeLimit to 0xffffffff effectively sets

RSL to be as large as paged pool allows (80 percent of paged pool size).

In the initial release of Windows NT, the paged pool defaults to 32 MB, so

the default RSL is 8 MB (enough to support approximately 5000 users). The

paged pool can be set to a maximum of 128 MB, so the RSL can be no larger

than about 102 MB, supporting about 80,000 users (surpassing the realistic

limitations of other parts of the system).

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Determining Whether App Is Running as Service or .EXE

Article ID: Q94994

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

When debugging Windows NT services, it may be necessary for the service

application to be run interactively.

In this case, the application may determine whether it is being run as a

service or as an executable (interactively) by checking GetLastError()

after the call to StartServiceCtrlDispatcher() in the application's startup

code.

If the application is being run as an executable, the call to

GetLastError() will return with the following:

   ERROR_FAILED_SERVICE_CONTROLLER_CONNECT

An alternative method is to check the return value from GetConsoleMode().

For example:

   ret = GetConsoleMode (GetStdHandle (STD_OUTPUT_HANDLE), &mode);

Although the std handles may exist, they almost certainly will not be

console handles unless there is a console attached. GetConsoleMode() will

fail (with ERROR_INVALID_HANDLE) for non-console handles.

Sample Code

-----------

// Call StartServiceCtrlDispatcher() to set up the control

// interface. The API won't return until all services have been

// terminated. At that point, we just exit. See the

// StartServiceCtrlDispatcher() entry in Windows Help.

if (!StartServiceCtrlDispatcherW(ElfSvcDispatchTable) &&

   GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {

   // Set a flag indicating you're running as an .EXE, not a service.

}

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseService


INF: VirtualLock() Only Locks Pages into Working Set

Article ID: Q94996

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

VirtualLock() causes pages to be locked into an application's working set

(virtual memory); it does not lock them absolutely into physical memory.

VirtualLock() essentially means "this page is always part of the process's

working set."

The system is free to swap out any virtually locked pages if it swaps out

the whole process. And when the system swaps the process back in, the

virtually locked pages (similar to any virtual pages) may end up residing

in different real pages.

It is wise to use VirtualLock() very sparingly because it reduces the

flexibility of the system.

Depending upon memory demands on the system, the memory manager may vary

the number of pages a process can lock. Under typical conditions you can

expect to be able to VirtualLock() approximately 28 to 32 pages.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMm


INF: Reducing the Count on a Semaphore Object

Article ID: Q94997

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

ReleaseSemaphore(), which increments the count of a given semaphore object

by a specified amount, will not take a negative value.

If, for some reason, you want to reduce the number of available semaphore

"slots" to temporarily restrict or reduce access, you may loop calling

WaitForSingleObject() with a zero timeout, counting the number of times it

succeeds. When you no longer need to hold the semaphore slots, call

ReleaseSemaphore() with the number of slots counted.

Note that this method does not prevent other threads from taking a

semaphore slot when your thread is looping.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Trapping Floating-Point Exceptions Under Windows NT

Article ID: Q94998

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The _controlfp() function is the portable equivalent to the _control87()

function.

To trap floating-point (FP) exceptions via try-except (such as

EXCEPTION_FLT_OVERFLOW), insert the following before doing FP operations:

   // Get the default control word.

   int cw = _controlfp( 0,0 );

   // Set the exception bits ON.

   cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);

   // Set the control word.

   _controlfp( cw, MCW_EM );

This turns on all possible FP exceptions. To trap only particular

exceptions, choose only the flags that pertain to the exceptions desired.

Note that any handler for FP errors should have _clearfp() as its first FP

instruction.

MORE INFORMATION

================

By default, Windows NT has all the FP exceptions turned off, and thus

computations result in NAN or INFINITY rather than an exception. Note,

however, that if an exception occurs and an explicit handler does not exist

for it, the default exception handler will terminate the process.

If you want to determine which mask bits are set and which are not during

exception handling, you need to use _clearfp() to clear the floating-point

exception. This routine returns the existing FP status word, giving the

necessary information about the exception. After this, it is safe to query

the chip for the state of its control word with _controlfp(). However, as

long as an unmasked FP exception is active, most FP instructions will

fault, including the fstcw in _controlfp().

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseExcept


INF: FormatMessage() Converts GetLastError() Codes

Article ID: Q94999

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The FormatMessage() application programming interface (API) allows you

to convert error codes returned by GetLastError() into error strings,

using FORMAT_MESSAGE_FROM_SYSTEM in the dwFlags parameter.

Example

-------

// This code sample demonstrates how to get the system message string:

LPVOID lpMessageBuffer;

FormatMessage(

  FORMAT_MESSAGE_ALLOCATE_BUFFER |

  FORMAT_MESSAGE_FROM_SYSTEM,

  NULL,

  GetLastError(),

  MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),

  (LPTSTR) &lpMessageBuffer,

  0,

  NULL );

//... now display this string

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: FlushViewOfFile() on Remote Files

Article ID: Q95043

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

When flushing a memory-mapped file over a network, FlushViewOfFile()

guarantees that the data has been written from the workstation, but not

that the data resides on the remote disk.

This is because the server may be caching the data on the remote end.

Therefore, FlushViewOfFile() may return before the data has been physically

written to disk.

However, if the file was created via CreateFile() with the flag

FILE_FLAG_WRITE_THROUGH, the remote file system will not perform lazy

writes on the file, and FlushViewOfFile() will return when the actual

physical write is complete.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: Interprocess Communication Under Windows NT and on Win32s

Article ID: Q95900

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The following are some of the standard mechanisms available for

interprocess communication (IPC): NetBIOS, mailslots, windows sockets

(winsock), named pipes, anonymous pipes, semaphores, shared memory, and

shared files. Other IPC mechanisms available on Microsoft systems include

DDE, OLE, memory-mapped files, Windows messages, Windows atoms, the

registration database, and the clipboard.

MORE INFORMATION

================

The table below denotes what platforms and subsystems provide which IPC

mechanisms (note: this does not imply that all the mechanisms will

interoperate between different subsystems):

Interprocess Communication Mechanisms

-------------------------------------

   IPC  Mechanism  Win32  Win32s(1)  Win16(2)  MS-DOS(2)  POSIX OS/2

   --------------  -----  ---------  --------  ---------  ----- ----

              DDE   YES      YES       YES        NO       NO     NO

              OLE   YES      YES       YES        NO       NO     NO

          OLE 2.0   YES       NO       YES        NO       NO     NO

          NetBIOS   YES      YES       YES        YES      NO    YES

      Named pipes   YES      YES(3)    YES(3)    YES(3)   YES(6) YES

  Windows sockets   YES(4)   YES       YES(4)     NO       NO(5)  NO

        Mailslots   YES      YES(3)     NO        NO       NO    YES

       Semaphores   YES       NO        NO        NO      YES    YES

              RPC   YES      YES(7)    YES       YES       NO     NO

 Mem. Mapped File   YES      YES        NO        NO       NO     NO

      WM_COPYDATA   YES      YES       YES        NO       NO     NO

(1) Win32s an extension to Windows 3.1, which allows Win32 applications

    to run under Windows 3.1. Win32s supports all the Win32 APIs, but

    only a subset provides functionality under Windows 3.1. Those APIs

    that are not functional return ERROR_CALL_NOT_IMPLEMENTED.

(2) This is technically not a subsystem.

(3) Cannot be created on Win16 and MS-DOS workstations, but can be opened.

(4) Via the Windows sockets API.

(5) Currently BSD-style sockets are under consideration for the POSIX

    subsystem.

(6) The POSIX subsystem supports FIFO queues, which do not interoperate

    with Microsoft's implementation of named pipes.

(7) Win32s version 1.1 provides network support through Universal Thunks.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseIpc


SAMPLE: How to Reboot or Shut Down Programmatically

Article ID: Q95966

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The BOB (big orange button) sample demonstrates the steps necessary to

reboot or shut down the machine in Windows NT and Win32s programmatically.

A similar method can be used to log off a user. The steps are as follows:

1. Check to see if the machine is running Windows NT; if so:

   a. Get the security token.

   b. Fetch the LUID for the SeShutdownPrivilege; this is required only

      for rebooting and shutting down the machine.

   c. Enable the shutdown privilege.

2. Use ExitWindowsEx() to log off, shut down or reboot the machine.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. The samples are divided into two group: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory; small samples

available on the CD in the \Q_A\SAMPLES directory.

Note that this sample is also available in Microsoft Visual C++ 32-bit

edition, but it is called EXITWIN.

MORE INFORMATION

================

CAUTION: Use this API (application programming interface) with care *and*

with plenty of warning so that a user is not rudely surprised.

There are two methods to prevent the system from shutting down, one at the

application level and one at the system level. At the application level,

process the WM_QUERYENDSESSION message so the application can ask the user

whether he or she wants to save any data that has not been backed up to

disk. Then, return TRUE assuming the process can shut down safely or FALSE

if it cannot [note: this will not keep the machine from rebooting or

shutting down if the parameter to ExitWindowsEx() was or'ed with

EXW_FORCE]. At the system level, it is possible to remove the rights of

certain users/groups to reboot the machine. This is done via the

UserManager application.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMisc


INF: Validating User Accounts (Impersonation)

Article ID: Q96005

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Some applications need the ability to execute processes in the context of

another user. This impersonation restricts (or expands) the permissions of

the account in which the application was executed (file access, permission

to change system time, permission to shut down the system, and so forth).

For example, an administrator executes a network server program that allows

remote users to log on to the system and perform actions, as if they were

logged on to the system locally. Because the administrator initiated the

server program and is currently logged on, all actions the server program

performs will be in the security context of the administrator. If a guest

user logs on remotely, he/she will have all the permissions the

administrator account has.

With the Win32 API, impersonating a remote client is possible only via the

ImpersonateDDEClientWindow(), ImpersonateNamedPipeClient() and

RpcImpersonateClient() APIs.

MORE INFORMATION

================

A common application of impersonation is network server programs (daemons).

For example, a remote login daemon needs a user to be able to to log in to

a remote host and have the host impose all restrictions of the client login

account.

If the daemon is using named pipes, dynamic data exchange (DDE), or a

remote procedure call (RPC) (using the named pipes transport), the client

account may be impersonated on the server daemon, which will impose all the

restrictions of the client's user account.

Using other network interfaces (such as Windows sockets--network

programming interfaces), security cannot be monitored by the system. A

workaround would be to impose password-level security on "login" to the

application. The passwords would be maintained by the application in a

private accounts database. However, none of the user actions are performed

in the security context of the actual client user's account. Therefore,

after the server/daemon has validated the client, the server must be

careful to only perform actions on behalf of the client that the server

knows the client should be allowed to do.

Another option is to create a network share with restricted access. The

WNetAddConnection2() API can verify access to this system resources [disk

or printer network resource (share)]. If the network share was set up to

allow access by a restricted group of people, the WNetAddConnection2()

could validate actual user accounts, maintained by Windows NT. As with the

previous option, the daemon must be careful to perform only restricted

actions on behalf of the client. This option could be used for file server

daemons.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Chaining Parent PSP Environment Variables

Article ID: Q96209

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Some MS-DOS applications change the environment variables of their parent

application by chaining through the program segment prefix (PSP). With

Windows NT, this functionality doesn't work if the parent is a 32-bit

application.

MORE INFORMATION

================

When an MS-DOS application is started from a single command shell (SCS),

the application inherits a new copy of the environment variables. Any

attempts by the MS-DOS application to modify its parent's environment

variables will not work. When the MS-DOS application exits, the SCS will be

"restored" to its original state. If another MS-DOS application is started,

the second application will receive the same environment that the first MS-

DOS application received.

If an MS-DOS application (B) is spawned by another MS-DOS application (A),

any modifications to application A's environment variables will be

reflected when application B exits.

For more information on how environment variables are set, please see the

following article(s) in the Microsoft Knowledge Base:

   ARTICLE-ID: Q96268

   TITLE     : How Environment Variables Are Set in Windows NT

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Distinguishing Between Keyboard ENTER and Keypad ENTER

Article ID: Q96242

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

It is possible using ReadConsoleInput() or PeekConsole() to distinguish

between the ENTER key on the main keyboard and the ENTER key on the numeric

keypad. The KEY_EVENT_RECORD structure in the INPUT_RECORD structure must

be used to distinguish between the two keys.

MORE INFORMATION

================

The following illustrates what the KEY_EVENT_RECORD structure is filled

with after a keyboard ENTER key versus a numeric keypad ENTER key is

pressed.

Keyboard ENTER Key

------------------

   KeyEvent.wRepeatCount     = 1

   KeyEvent.wVirtualKeyCode  = 13

   KeyEvent.wVirtualScanCode = 28

   KeyEvent.dwControlKeyState= 00000000

Numeric Keypad ENTER Key

------------------------

   KeyEvent.wRepeatCount     = 1

   KeyEvent.wVirtualKeyCode  = 13

   KeyEvent.wVirtualScanCode = 28

   KeyEvent.dwControlKeyState= 00000100

In the case of the numeric keypad ENTER key, in dwControlKeyState, the

ENHANCED_KEY bit is set.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCon


INF: Win32 .DEF File Usage in Applications and DLLs

Article ID: Q96374

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Certain aspects of Win32 .DEF file usage are the same as Win16 .DEF file

usage; however, there are a number of important changes.

MORE INFORMATION

================

The .DEF files are not necessary to build an application (because callbacks

don't need to be exported), but they can be used. However, the linker will

not directly accept a .DEF file. The .DEF file is passed to the Library

Manager. The Library Manager creates an export module (.EXP file), which

needs to be linked with the application. Due to the nature of this step, it

is necessary to include at least one export in the .DEF file.

Certain changes can be made without the .DEF file. If you need to set

section attributes, you can use the linker -SECTION option. If you need to

embed a description or a version string, you can use #pragma comment in the

source files. Note that there currently is no support for the STUB

statement either via the command line or via a .DEF file. The stub is hard-

coded into the linker. This functionality is being considered for inclusion

in either the final release of the Win32 Software Development Kit (SDK) or

in Microsoft Visual C++ 32-bit edition.

In Win32 development, a .DEF file is primarily used to export functions

from a dynamic-link library (DLL). Again, the linker will not accept the

.DEF file. Use the Library Manager to create the .EXP file to be linked

with the DLL and to create an import library (.LIB file), which will be

linked with any application or DLL that wants to use the DLL functions.

The process of using a .DEF file to export functions requires that the

EXPORTS listed in the .DEF file exactly match their functions' decorated

names. The possible types of decorated names include:

1. __cdecl, where names are decorated with an underscore prefix

2. __stdcall, where names are decorated with an underscore prefix and an

   @<number> suffix, where <number> is the number of bytes in the

   argument list

3. C++, where the decorated name can be looked up in the output of

   link -dump -symbols

The Library Manager handles the name decoration for you if you pass it the

object files on the command line. There is a special pass during which the

Library Manager takes the undecorated name from the .DEF file, searches the

object files, and provides the decorated name in the export module

generated.

NOTE: For C++ overloaded functions or if two classes contain member

functions that have the same name, the librarian cannot determine which

decorated name to use and will issue an error. In this case, the fully

decorated name must be provided in the .DEF file. There is no way to

specify a scope resolution operator in the .DEF file.

For a sample makefile, see the SELECT or SPINCUBE samples.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseDll


SAMPLE: Demonstration of the Win32 Debug API

Article ID: Q96396

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The Debug Event Browser (DEB) Win32 SDK sample demonstrates the new Win32

Debug API. This sample acts as a debugger for both newly created debuggee

processes or attaches to current active processes.

DEB is not a debugger in the traditional sense; it is a browser as its name

implies. DEB displays the debug events, and their relevant properties, as

they occur and invokes the default handlers supplied either by the debuggee

or the system. Only the minimal debug event handling is imposed such that

the debug events are displayed and the debuggee is continued on its normal

course of execution.

The sample is source code compatible for both the Intel 80x86 and MIPS

R4000 Windows NT platforms.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The following is a complete list of files accompanying the Debug Event

Browser sample:

   DEB.BMP        DEB bitmap used by DEB.RTF

   DEB.DEF        DEB module definition file

   DEB.DLG        DEB dialog resource script file

   DEB.H          DEB ID values and user message defines

   DEB.HPJ        DEB help project file

   DEB.ICO        DEB main icon

   DEB1.ICO       DEB animated icon number one

   ...

   DEB8.ICO       DEB animated icon number eight

   DEB.RC         DEB resource file

   DEB.RTF        DEB help topic file

   DEBDEBUG.C     DEB debug support functions

   DEBDEBUG.H     DEB debug support functions header

   DEBMAIN.C      DEB main module - WinMain and callbacks

   DEBMAIN.H      DEB main module header

   DEBMISC.C      DEB miscellaneous support functions

   DEBMISC.H      DEB miscellaneous support functions header

   LINKLIST.C     Ordered doubled-linked list library

   LINKLIST.H     Ordered doubled-linked list library header

   MAKEFILE       Make/Nmake file for the entire sample

   README.TXT     This file you are presently reading

   TOOLBAR.BMP    Toolbar bitmap used by DEB.RTF

   TOOLBAR.C      Toolbar functions

   TOOLBAR.DEF    Toolbar module definition file

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMisc


SAMPLE: Demonstration of Using GetLocaleInfoW

Article ID: Q96398

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The LOCALE sample is a simple dialog box which provides an interface

between the user and the system GetLocaleInfoW() API.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMisc


SAMPLE: How to Share Memory Between Processes

Article ID: Q96400

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The MEMORY sample demonstrates the use of the file-mapping application

programming interfaces (APIs) to create a share memory between processes.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. The samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

Server

------

The "server" sets up the named share memory, and can be created by choosing

Server from the Create menu. This opens up a multiple document interface

(MDI) server child and swaps the menu bar to the server menu bar. The

server menu bar includes three choices: Create, Server, and Window.

To set up the equivalent of a named share memory:

1. From the Server menu, choose Create File. This brings up the File

   Type dialog box. The user can create either a memory page file or a

   physical file by choosing the Page File or the Map File button,

   respectively, to back up the soon-to-be-created named share memory.

   If the Map File button is choosen, the named share memory will be

   backed up by a physical file on the disk. If the Page File button

   is choosen, the memory will be backed up by the memory page file.

2. From the Server menu, choose Create File Mapping. This brings up

   the Map Name dialog box. The user then can specify a name for the

   memory map file object that is created for the file created in step

   1 above.

   This name is used to identify the share memory by the clients in

   the other processes.

3. From the Server menu, choose Map View Of File. This essentially

   maps the map file object created in step 2 above into the process's

   address space.

4. From the Server menu, choose Access. This creates a multiline edit

   control (MLE) inside the MDI server child. Whatever is written in

   the MLE is put in the map file object.

Client

------

The "client" connects to the named share memory created by the server in

another process. A client can be created by choosing Client from the Create

menu. This opens up an MDI client child and swaps the menu bar to the

client menu bar. The client menu bar includes three choices: Create,

Client, and Window.

To set up the connection to the named share memory:

1. From the Client menu, choose Open File Mapping. This brings up the

   Map Name dialog box. The user can then enter the name of the map

   file object that the client wanted to connect to.

2. From the Client menu, choose Map View Of File. This essentially

   maps the map file object opened in step 1 above into the process's

   address space.

3. From the Client menu, choose Access. This creates an MLE inside the

   MDI Server child. Whatever was written in the map file object by

   the server will be shown in this MLE.

   The client synchronizes with the server at a regular interval.

4. From the Client menu, choose Refresh Now to refresh the contents of

   the map file object.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMm


SAMPLE: Demonstrating the Creation of Multiple Threads

Article ID: Q96401

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The MLTITHRD sample demonstrates thread creation.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. The samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The MLTITHRD sample is a multiple document interface (MDI) application.

When an MDI child is created, a drawing thread is also created with it. The

drawing thread merely draws color boxes randomly inside the MDI child

window.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseProcThrd


SAMPLE: Constructing and Using a Message Table Resource

Article ID: Q96402

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The MSGTABLE sample demonstrates how to construct and use a message table

resource in your application. The sample message table (MESSAGES.MC) for

the message compiler (MC.EXE) shows the format of a typical message table

source file. Note that some of the entries for each message are optional

but are shown for demonstration purposes. See the documentation in the

TOOLS.HLP file on the message table compiler for more information on which

fields are optional.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. The samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

This sample shows how to create a resource-only dynamic-link library (DLL)

that contains nothing but the message table resource. The DLL source file

(MESSAGES.C) has a stub entry point that merely returns TRUE. This is due

to the requirement that a DLL have at least one entry point, so we need to

have one for our resource-only DLL.

The MSGTEST.EXE executable shows how to load the message table DLL, how to

extract the message text from the resource with the FormatMessage API, and

how to decode the various bits in the message ID. Note that the MESSAGES.H

include file to the executable is created during the make process by the

message compiler (MC.EXE) as it is creating the binary resource file from

the message table source file.

The makefile should be useful to demonstrate how to set up your dependency

rules for your message table source files and message table DLL.

This sample could be easily modified to link the message table resource

directly into your executable rather than into a stand-alone DLL; there is

no requirement that the message table resource be located only in a DLL,

although this is the common case.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMisc


SAMPLE: Sharing Named Memory Between Two Processes

Article ID: Q96403

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

SHAREMEM and OTHRPROC are two samples which work together to demonstrate

sharing named memory between two separate processes. These samples must be

run together.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

To use: first start an instance of SHAREMEM. A window will appear, divided

into an upper and lower section. The upper section will have two edit

fields: one displaying the mouse pointer's X-coordinates, and the other the

pointer's Y coordinates, as the mouse moves in the lower section.

Start an instance of OTHRPROC. Allow OTHRPROC to keep focus, but move the

pointer around over the SHAREMEM'S window. OTHRPROC has a similar window

configuration; however, you will notice that the X and Y coordinates of the

mouse as it moves over the SHAREMEM window are the values that appear in

the edit fields of OTHRPROC. To emphasize this, a crosshair will appear in

OTHRPROC's lower section; its movements relative to the mouse position in

SHAREMEM's window.

What's happening: When SHAREMEM is started, it creates and allocates a

piece of named shared memory the size of a DWORD (the size needed to hold

the mouse cursor's X and Y coordinates) using CreateFileMapping(). As the

mouse pointer is moved across the window, the WM_MOUSEMOVE messages are

trapped, and the coordinates are written to the upper edit fields and to

the piece of named shared memory.

When OTHRPROC is started, it gets access to the named shared memory by

calling OpenFileMapping() and MapViewOfFile(). OTHRPROC then uses a thread

to poll and read the X and Y coordinates written to the shared memory by

SHAREMEM. It captures the coordinates and draws a bit map of a crosshair in

the specified location.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMm


SAMPLE: Platform Detection

Article ID: Q96404

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The PLATFORM sample shows how to determine which Win32 platform a Win32

application is running under. GetVersion() will return with the high bit of

the high word cleared if the operating platform is Windows NT and it will

be set otherwise.

Win16 applications can determine whether there are running on Win32/NT or

Win16/MS-DOS by examining the flags return by GetWinFlags(). The WF_WINNT

bit (0x4000) will be set on Windows NT and clear otherwise. The return from

GetWinFlags() will not be equal to WF_WINNT or any other constant.

This sample is included with the Microsoft Win32 SDK for Windows NT. The

samples are divided into two groups: samples (optionally) installed into

the \MSTOOLS\SAMPLES directory, and small samples available on the CD in

the \Q_A\SAMPLES directory.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMisc


SAMPLE: Named Pipe Client/Server Demonstration

Article ID: Q96406

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The NAMEPIPE sample demonstrates the use of named pipes. The basic design

consist of a server application (NPSERVER) serving multiple client

applications (NPCLIENT). The user can use the client applications as an

interface to all of the other client applications via the server. The

effect is a simple communication program that can be used over the network

between multiple clients.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The sample has the NPSERVER application launch a new thread, which creates

and services a new instance of the server side of the named pipe every time

a client connects to it. You need only start one instance of the NPSERVER

application. It will service up to 100 instances of the NPCLIENT

application. (Note that the 100 instance limit is hard coded into the

sample. It does not reflect the number of named pipe instances you can

create, which is virtually infinite.)

TO USE:

Start an instance of NPSERVER.  A window will appear.

Start an instance of NPCLIENT. Two dialog boxes will appear, one on top of

the other. The top level dialog box will prompt you for a share name and a

client or user name. If the instance of NPCLIENT is local to (on the same

machine as) the NPSERVER instance, enter a '.' for the share name.

Otherwise, enter the machine name of the server that the NPSERVER instance

was started on, i.e. 'FoobarServer'. For the client or user name, enter any

name you wish to be identified with. Hit enter or click the OK button.

The upper dialog box will go away, and you'll see the Client dialog box of

NPCLIENT. It consists of two edit fields and a 'Send' button. You will be

able to read messages from other clients (and yourself) in the larger/upper

edit field. (Note, if the message seems garbled, make sure the cursor of

the edit field is located in the lower left hand corner of the field.) The

smaller edit field is used to type messages. To send a message: type

something in the lower/smaller edit field, and hit enter or click the Send

button. The message will appear in the larger edit field of all the clients

connected to the NPSERVER instance; prepended by the user name you

selected. Note that the user name you selected will be entered into the

caption bar of the NPCLIENT instance. This allows you to more easily keep

track of multiple instances of NPCLIENT on the same machine.

At the same time the top level dialog box was dismissed from the NPCLIENT

instance, the NPSERVER window was updated with the picture of a red spool

of thread accompanied by the user name you selected. This red spool

indicates an active client thread connected to NPSERVER. The spool may be

connected to other spools with a thin blue line (similar to the way the

File Manager connects files or directories). Any time a client disconnects

from NPSERVER; the spool representing it will be grayed out.

DESIGN:

The NPSERVER application launches multiple instances of a server thread.

When the application is started, the first thread is created. It creates an

instance of the server side of the named pipe, and waits for a client to

connect. Once a client connects, another thread is started and it too

blocks waiting for a client. Meanwhile, the first thread updates a global

array of client information with this specific client's information. The

thread then enters a loop reading from this client. Any time this specific

client sends a message, this server thread will call a function (TellAll)

which will write the message to all the clients that have been listed in

the global array.

On the client side, NPCLIENT tries to connect to the named pipe with a call

to CreateFile(). Once it has connected, it creates a thread which loops and

reads any message from the server side. Once a message is read, it is

printed in the larger edit field. Any time the user hits the Send button,

the main thread grabs any text in the lower edit field, and writes it to

the server.

The steps between NPSERVER and an instance of NPCLIENT looks like this:

   NPSERVER                           NPCLIENT

   --------                           --------

   CreateNamedPipe()

   ConnectPipe()   // Blocks

                                      CreateFile()  //Connects to pipe.

                                      spawn separate thread to read pipe

   return from block

   updates array of clients

   spawn another server thread

   Loop

      ReadFile() // Blocks on overlap

                                      WriteFile() // User hits Send.

      return from block

      WriteFile() // Broadcast

   End loop      // client breaks off

                                      ReadPipe Thread:

                                      Loop

                                         ReadFile()

                                         block till server broadcasts

                                         return from block.

                                         put string in edit field.

                                      End loop // server breaks off

The overlapped structure should be used anytime a pipe is expected to block

for any length of time on a read or write. This allows the thread to return

immediately from a read or write to service any other part of your

application. The overlapped structure should also be used on a named pipe

anytime you expect to do simultaneous reads and writes.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseIpc


SAMPLE: Using API Functions to Access the Registry

Article ID: Q96408

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The REGISTRY sample is a simple utility which demonstrates the Registry API

functions needed to access the Registry. REGISTRY can be used to climb up

and down the various branches of the Registry tree, displaying the

individual key's data values. It can also be used to print specified trees

to a file named Registry.txt.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

To use: start an instance of the sample. A dialog box will appear with

several edit fields, list boxes and buttons. The listbox in the center of

the dialog box (labeled CHILD KEYS: at the bottom) will always hold the

child keys of the current key. Initially it has four entries, representing

the four pre-defined key handles of the Registry: HKEY_LOCAL_MACHINE,

HKEY_CURRENT_USER, HKEY_USERS, and HKEY_CLASSES_ROOT. If you double click

on any of these entries, or high light it and press the "Next/Down" button;

the key that you just selected will appear in the edit field "Key Name",

and the children of that selected key will replace the entries in "CHILD

KEYS:" list box. I.e. if you select HKEY_LOCAL_MACHINE, that name will be

present in "Key Name", and it's children will appear in the list box:

HARDWARE, SECURITY, SOFTWARE, and SYSTEM. To proceed deeper into the tree,

double click another child. To back out of the Registry, double click on

the ".." at the top of the listbox, or press the "Back/Up" button.

If the current key has values associated with it, the name of the values

will be listed in the right hand listbox (labeled "VALUES:"). If it has now

values, "VALUES:" will be followed by a "0". Once you come upon a key that

does have values associated with it, you can double click on any of the

values in this list box. At the bottom of the dialog box are two edit

fields: "Value: Data Type", and "Value: Data Entry". By double clicking a

value entry, these edit fields will be filled in the data's type and the

data's value. I.e. if you follow the tree down to

HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System; and double click on the

entry "1) Identifier", the "Value: Data Type" field will be filled with

"REG_SZ: A null-terminated Unicode string"; and the "Value: Data Entry" may

be filled in with something such as "AT/AT COMPATIBLE"

If the current key has a Class type associated with it, it will appear in

the "Class" edit field. The "ACL" edit field is not implemented.

You can use REGISTRY to write any part of the Registry Tree to a file

called REGISTRY.TXT. To do this, select either the "Full" or "Trimmed"

buttons (this specifies either writing all of the key entries, or only

those having Value data associated with them); and press the "Print Branch"

button. REGISTRY will begin at the current branch, and will proceed

recursively down the branches to the end of the tree, writing the

information to the file. To write the entire tree, print each of the four

pre-defined keys. Note, this can make for a rather large file (700Kb at the

time this was written).

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMisc


SAMPLE: Using Semaphores to Control Threads

Article ID: Q96410

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The SEMAPHOR sample application shows how to control four threads with a

semaphore. It demonstrates this by having four threads competing for the

right to draw their color to a rectangle in the center of the window.

Access to the center area is controlled by the semaphore.

MORE INFORMATION

================

When you start the application you will see five rectangles: a dynamic

rectangle in the center (always changing color), and four static rectangles

surrounding it. Each of the four rectangles has its own color: red, blue,

green, and gray. The one in the center alternates between these colors.

The four static rectangles represent four threads. These four threads

compete for the rectangle in the middle, and their access is controlled by

the semaphore. When a thread gains control of the semaphore, it gets to

draw its color in the center rectangle. (Note: The threads do not actually

draw any of the four static rectangles. To make the code simpler, this is

handled in the WM_PAINT message in the MainWndProc function. The rectangles

are used only as visual representations of the threads. The threads do,

however, draw the rectangle in the center with their specific color.)

The semaphore has a use count. When it is set to zero, any thread can

access the semaphore and execute the code within its "semaphore gate" by

using WaitForSingleObject(). When the thread gains control of the semaphore

using this call, the use count is incremented by 1. When the thread is done

executing its code, it can call ReleaseSemaphore(). This will decrement the

count by whatever value you indicate (this code uses 1), signaling to any

other thread that it may gain control of the semaphore.

NOTE: Any thread that has access to the semaphore may decrement the

semaphore's use count with ReleaseSemaphore(); the thread does not have to

have control of the semaphore at the time.

In this code, the WM_CREATE message in MainWndProc creates a semaphore. The

four threads are then created, each waiting on the semaphore.

Each of the threads loop, blocking on a WaitForSingleObject() call. Once

any thread has set the use count to 0, the thread gets to draw the center

rectangle with its color and then sleeps for half a second before freeing

the semaphore again. The thread then runs through the loop again.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMisc


SAMPLE: Demonstration of Opening and Terminating a Process

Article ID: Q96412

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The TERMPROC sample demonstrates how to open and terminate a process in

situations where it is impossible to do so otherwise. PView can be used to

obtain the process ID (PID) of the process to be terminated. Note that the

application does the decimal to hexadecimal conversion as is necessary.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. The samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseProcThrd


SAMPLE: Using TLS to Store Thread-Specific Data in a DLL

Article ID: Q96413

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The TLS sample demonstrates using thread local storage (TLS) to store

thread-specific data in a dynamic-link library (DLL). As each thread

attaches, the memory is alloc'd and filled. As each thread detaches, it is

retrieved; as the process detaches, the TLS is freed.

This is a very basic sample, and the calls into the DLL that cause TLS to

be allocated and filled don't really do anything; however, this should be a

good basis on which to build TLS code.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. The samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMm


INF: Priority Inversion and Windows NT Scheduler

Article ID: Q96418

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Threads are scheduled according to their priority. When the kernel is

choosing which thread will execute on a processor, the highest dynamic-

priority thread is picked. Priority inversion occurs when two (or more)

threads with different priorities are in contention to be scheduled.

Consider a simple case with three threads: Thread 1 is high priority and

becomes ready to be scheduled, while thread 2, a low-priority thread, is

executing in a critical section. Thread 1, the high-priority thread, begins

waiting for a shared resource from thread 2. A third thread has medium

priority. The third thread receives all the processor time, because the

high-priority thread (thread 1) is busy waiting for shared resources from

the low-priority thread (thread 2). Thread 2 won't leave the critical

section, because it isn't the highest priority thread and won't be

scheduled.

The Windows NT scheduler solves this problem by randomly boosting the

priority of threads that are ready to run (in this case the low priority

lock-holders). The low priority threads run long enough to let go of their

lock (exit the critical section), and the high- priority thread gets the

lock back. If the low-priority thread doesn't get enough CPU time to free

its lock the first time, it will get another chance on the next scheduling

round.

MORE INFORMATION

================

Each Process has a base priority. Each thread has a base priority that is a

function of its process base priority. A thread's base priority is settable

to:

 - 1 or 2 points above the process base

 - equal to the process base

 - 1 or 2 points below the process base

Priority setting is exposed through the Win32 API. In addition to a base

priority, all threads have a dynamic priority. The dynamic priority is

never less than the base priority. The system raises and lowers the dynamic

priority of a thread as needed.

All scheduling is done strictly by priority. The scheduler chooses the

highest priority thread which is ready to run. On a multi-processor (MP)

system, the highest N runnable threads run (where N is the number of

processors). The thread priority used to make these decisions is the

dynamic priority of the thread.

When a thread is scheduled, it is given a quantum of time in which to run.

The quantum is in units of clock ticks. The system currently uses 2 units

of quantum (10ms on r4000 and 15ms on x86).

When a thread is caught running during the clock interrupt, its quantum is

decremented by one. If the quantum goes to zero and the thread's dynamic

priority is not at the base priority, the thread's dynamic priority is

decremented by one and the thread's quantum is replenished. If a priority

change occurs, then the scheduler locates the highest priority thread which

is ready to run. Otherwise, the thread is placed at the end of the run

queue for it's priority allowing threads of equal priority to be "round

robin" scheduled. The above is a description of what is usually called

priority decay, or quantum and priority decay.

When a thread voluntarily waits (an an event, for I/O, etc), the system

will usually raise the thread's dynamic priority when it resumes.

Internally, each wait type has an associated priority boost. For example, a

wait associated with disk I/O has a one point dynamic boost. A wait

associated with a keyboard I/O has a 5 point dynamic boost. In most cases,

this boost will raise the priority of the thread such that it can be

scheduled very soon afterwards, if not immediately.

There are other circumstances under which priority will be raised. For

example, whenever a window receives input (timer messages, mouse move

messages, etc), an appropriate boost is given to all threads within the

process that owns the window. This is the boost that allows a thread to

reshape the mouse pointer when the mouse moves over a window.

By default, the foreground application has a base process priority that is

one point higher than the background application. This allows the

foreground process to be even more responsive. This can be changed by

bringing up the System applet, selecting the Tasking button, and choosing a

different option.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseProcThrd


INF: Security and Screen Savers

Article ID: Q96780

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Screen savers are user-mode applications that execute in a different

desktop (see the note at the end of the article). Therefore, a screen saver

cannot enumerate windows of user-mode applications. This design prevents

unauthorized users from viewing the contents of applications displayed on

the screen. For secure screen savers (those that ask for a password), this

adds a further layer of protection.

Screen savers also execute in the security context of the logged-on user. A

screen saver may call ExitWindowsEx(), to log off from or shut down the

system, or any other application programming interface (API) that the

logged-on user has permission to perform.

MORE INFORMATION

================

A sample screen saver SCRNSAVE is distributed on the Win32 SDK CD.

NOTE: A desktop is a virtual screen. Windows NT currently has three

desktops--the main desktop, the WinLogon desktop, and a desktop for screen

savers. The Win32 APIs do not allow creation of multiple desktops.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


SAMPLE: Examining Security Descriptors (SDs)

Article ID: Q97657

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The CHECK_SD sample can be used to examine security descriptors.

In the Win32 API helpfile, if you click Search, then "Security Overview,"

and then from the list of topics under Security Overview choose the

subtopic "Allowing Access," you will find the comment:

   NOTE: It is fine to write code like this that builds security

   descriptors from scratch. It is, however, a good practice for

   people who write code that builds or manipulates security

   descriptors to first write code that explores the default security

   descriptors that Windows NT places on objects. For example, if

   Windows NT by default includes in a DACL an ACE granting the Local

   Logon SID certain access, it's good to know that, so that a

   decision not to grant any access to the Local Logon SID would be a

   conscious decision.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

Purpose of This Sample

----------------------

The comment in the helpfile is accurate; however, for many people the task

of examining the security descriptor (SD) is easier if there is sample code

to start from. Therefore, the purpose of this sample is to provide sample

code for use as a starting point from which to examine SD(s). This sample

examines the SD on files; this code can be modified to examine the SD on

other objects.

This sample is not a supported utility.

To Run the Sample

-----------------

Type Check_sd to check the SD on the \\.\A: device.

Type Check_sd d:\a.fil to check the SD on the d:\a.fil file. In this

case, drive D must be formatted NTFS, because only NTFS files have

SD(s).

Further Notes

-------------

 - If you recompile with the define set as follows

   #define I_DO_NOT_WANT_THIS_CODE_TO_CLUTTER_THIS_PROGRAM_S_OUTPUT (1==0)

   and re-run the program, the program will produce more output,

   including displaying all the information you can access in a Win32

   program from the process's Access Token, and the SDs of some

   sample objects.

 - If you log on, run with the program built to produce the extra

   output as mentioned just above, save that output to a file, then

   log off and re-run the program, save the output of this second run

   to a different file. With WinDiff, you can easily observe how the

   local logon SID really does change values for each logged on

   session.

 - A sample test you could run to exercise DACLs involves using the

    \Q_A\SAMPLES\SD_FLPPY sample in conjunction with this check_sd

    sample.

 - Perform the following series of steps:

    1. Log on to a machine as a local Administrator.

    2. Do the following:

          check_sd \\.\A: >out_bef.a

          check_sd \\.\B: >out_bef.b

    3. Log off.

    4. Log on to the same machine as Guest on the local machine domain.

    5. Do the following:

          sd_flppy

    6. Try the following:

          dir a:    (observe access denied)

          dir b:    (observe access denied)

          copy config.sys a:\   (get device not found)

          copy config.sys b:\   (get device not found)

    7. Log off.

    8. Log on to the same machine as a local Administrator.

    9. Do the following:

          check_sd \\.\A: >out_aft.a

          check_sd \\.\B: >out_aft.b

   10. Browse the differences between OUT_BEF.* and OUT_AFT.*

 - The above sample test demonstrates that the ACLs that sd_flppy

   applies survive logoffs. To demonstrate the DACLs do not survive

   rebooting, simply reboot, log back on as a local Administrator, and

      check_sd \\.\A: >out_rbt.a

      check_sd \\.\B: >out_rbt.b

   to see the DACLs are again as they were in the following:

      out_bef.a

      out_bef.b

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseSecurity


SAMPLE: Using Based Pointers to Share Memory

Article ID: Q97658

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

When several processes need to access shared data, there is no guarantee

that the shared memory is mapped to the same locations in all processes.

This can cause a problem when the data contains relative pointers because a

pointer value that is valid in one process's context may not be valid in

the context of the other processes.

BPOINTER is a sample that demonstrates the use of based pointers to allow

manipulation of shared data from several processes using memory mapped

files. This technique is applicable to all forms of shared memory.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The sample contains the following modules:

   READDATA.EXE   A console process that allows you to view the shared

                  data; it dereferences pointers as it encounters them.

   CHGDATA.EXE    A console process that lets you add elements to a shared

                  linked list.

Note, however, that based pointers reduce the performance of the

application using the pointers because the pointers must be resolved at run

time; that is, each access typically adds one machine instruction overhead

when dereferencing a pointer.

Once the files are compiled, execute CHGDATA.EXE and follow the

instructions posted there.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMm


INF: Default Stack in Win32 Applications

Article ID: Q97786

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

By default, space is reserved for applications in the following manner:

   1 megabyte (MB) reserved (total virtual address space for the stack)

   4K committed (total physical memory allocated when stack is

                 created)

   Note: The -heap linker option can be used to modify both of these

         values.

The operating system will grow the stack as needed by committing 4K blocks

out of the reserved stack memory. Once all of the reserved memory has been

committed, Windows NT will attempt to continue to grow the stack into the

memory adjacent to the memory reserved for the stack, as shown in the

following:

   |<--- Total 1 MB for stack --->|<--- Adjacent memory --->|

   --------------------------------------------------------

   |       |                      |                         |

   |  4K   |   1020K  ...         |       ...               |

   |       |                      |                         |

   --------------------------------------------------------

However, once the stack grows to the point that the adjacent area is not

free (and this may happen as soon as the reserved 1 MB has been committed),

the stack cannot grow any farther. Therefore, it is very risky to rely on

this memory being free. Applications should take care to reserve all the

memory that will be needed by increasing the amount of memory reserved for

the stack.

In other cases, it may be desirable to reduce the amount of memory reserved

for the stack.

The /STACK option in the linker and the STACKSIZE statement in the DEF file

can be used to change both the amount of reserved memory and the amount of

committed memory. The syntax for each method is shown below:

   /STACK:[reserve][,commit]

   STACKSIZE [reserve][,commit]

MORE INFORMATION

================

Each new thread gets its own stack space of committed and reserved memory.

If a new size is not specified in the CreateThread() call, the new thread

takes on the same stack size as the thread that created it, whether that be

the default value, a value defined in the DEF file, or by the linker

switch.

The system handles committing more reserved stack space when needed, but

cannot reserve or commit more than the total amount initially reserved (or

committed if no additional is reserved). Remember that the only resource

consumed by reserving space is addresses in your process. No memory or

pagefile space is allocated. When the memory is actually committed, both

memory and pagefile resources are allocated. There is no harm in reserving

a large area if it might be needed.

As always, automatic variables are placed on the stack. All other static

data is located in the process address space. Because they are static, they

do not need to be managed like heap memory.

Note that under Win32s, stacks are limited to a maximum of 128K.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMm


PRB: Code in DLL Causes Access Violation C00000005

Article ID: Q97787

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

A DLL entry point with __cdecl convention results in an access violation

(specifically, C0000005).

CAUSE

=====

Windows NT expects that the dynamic-link library (DLL) entry point will

have a calling convention of __stdcall. If the entry point is not

explicitly given a calling convention, the compiler's default convention is

__cdecl.

This is not an obvious mistake to track down. Under the debugger, you will

notice that you can trace into the entry point, but the next function call

will fail. Thus, it appears as if the execution of the entry point

succeeded. The problem is really that the stack was not properly cleaned

up.

RESOLUTION

==========

To correct the problem, do one of the following

 - Add WINAPI to the function prototype and declaration so that the

   function will have the __stdcall calling convention.

   -or-

 - Compile with -Gz so that by default, all functions will be

   declared with the __stdcall convention. If you are using

   NTWIN32.MAK, the macro "scall" is defined for this purpose.

MORE INFORMATION

================

The same problem occurs if callback functions, such as dialog box

procedures, are not declared __stdcall. The solutions described above

apply in this situation as well.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseDll


INF: The Use of the SetLastErrorEx() API

Article ID: Q97926

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SetLastErrorEx() is intended for better debugging support, not for passing

additional error information.

The SetLastErrorEx() application programming interface (API) differs from

the SetLastError() API only in that it raises a debug "RIP" event. The RIP

event is intended to give text to the debugger so that the user can retry,

ignore, and so forth, these errors. SetLastErrorEx() raises an exception

only if SetDebugErrorLevel() has been called by the debugger to allow the

errors to be passed on.

The error type can be determined from the debugger by examining the debug

event structure that is passed with the event. The debug event structure

contains a RIP_INFO substructure.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Windows NT Virtual Memory Manager Uses FIFO

Article ID: Q98216

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

On page 193 of "Inside NT," Helen Custer states that the Windows NT virtual

memory manager uses a FIFO (first in, first out) algorithm, as opposed to a

LRU (least recently used) algorithm, which the Windows virtual memory

manager uses. While it is true that FIFO can result in a commonly used page

being discarded or paged to the pagefile, there are reasons why this

algorithm is preferable.

Here are some of the advantages:

 - FIFO is done on a per-process basis; so at worst, a process that

   causes a lot of page faults will slow only itself down, not the

   entire system.

 - LRU creates significant overhead--the system must update its page

   database every single time a page is touched. However, the database

   may not be properly updated in certain circumstances. For example,

   suppose that a program has good locality of reference and uses a

   page constantly so that it is always in memory. The operating

   system will not keep updating the timestamp in the page database,

   because the process is not hitting the page table. Therefore this

   page may age even though it is in nearly constant use.

 - Pages that are "discarded" are actually kept in memory for a while,

   so if a page is really used frequently, it will be brought back

   into memory before it is written to disk.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMm


INF: File Manager Passes Short Filename as Parameter

Article ID: Q98575

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

When starting an application from File Manager by double-clicking a

document associated with the application, if the document resides on an

NTFS partition and has a long (non-8.3 form) filename, File Manager will

pass the short version of the filename (also known as the MS-DOS alias or

8.3 name) to the associated application. This is done for compatibility

reasons; applications not aware of long filenames (16-bit applications) can

still function correctly.

This can create confusion, however, if the application displays the name of

the file the application was started with; the short name is displayed even

though the long name was double-clicked.

You can avoid possible confusion by always expanding any filenames passed

to an application via the command line. Do this by calling the

FindFirstFile() application programming interface (API) on these filenames.

FindFirstFile() will always return the file system's version of the

filename in the WIN32_FIND_DATA.cFileName structure member, which the

application can then use in all further references to the file without any

problems.

Additional reference words: 3.10 file name

KBCategory: Prg

KBSubcategory: BseFileio


SAMPLE: Event Logging

Article ID: Q98613

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The sample called LOGGING shows how to do event logging. The sample

demonstrates how to set up the proper registry entries to register your

message dynamic-link library (DLL), how to make the actual event-log

entries, and how to pull event-log data from the event log.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. The samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseMisc


INF: Getting the Net Time on a Domain

Article ID: Q98722

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

When trying to execute

   net time /domain:egdomain /set

you may get a message saying the account is not known or the password is

invalid. This can happen if you are logged on using an account whose name

is spelled "Administrator", but the account is a different Administrator

account than the one on the domain controller. For example, if you are

logged on as EGMACHINE\Administrator, and attempt

   net time /domain:egdomain /set

you will get an error message because EGMACHINE\Administrator is not the

same account as EGDOMAIN\Administrator.

The solution is to log off EGMACHINE, log back on as EGMACHINE\PowerUsr1,

then execute the command. Note that a privilege is needed to set the time

on a machine. In the previous example, the account, EGMACHINE\PowerUsr1,

was used to remind us that power users have the needed privilege.

MORE INFORMATION

================

When running Windows NT while logged on to a domain, doing a NET TIME

without the /DOMAIN parameter, as mentioned above, probably will not yield

the desired results. However, because you are logged on to a domain, you

can do

   net time /domain /set

and a domain controller from the domain you are logged on to will be used.

In other words, if you are logged on to a domain, the /DOMAIN parameter is

necessary, but the actual domain name can optionally be left to default to

the domain you're currently participating in. If your machine is joined to

the a domain, that domain will be the default domain for NET TIME /DOMAIN.

If you are trying to get the time from EGDOMAIN and have done a prior

   net use \\egdomain\ipc$ /user:username

where username can be either a legitimate user name or domain name\user

name pair, or anything that will use the guest access), then the net time

will use the existing connection to the IPC$ share, using the different

user name.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Increased Performance Using FILE_FLAG_SEQUENTIAL_SCAN

Article ID: Q98756

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

There is a flag for CreateFile() called FILE_FLAG_SEQUENTIAL_SCAN which

will direct the Cache Manager to access the file sequentially.

Anyone reading potentially large files with sequential access can specify

this flag for increased performance. This flag is useful if you are reading

files that are "mostly" sequential, but you occasionally skip over small

ranges of bytes.

MORE INFORMATION

================

The effect on the Cache Manager of this flag is two-fold:

 - There is a minor savings because the Cache Manager dispenses with

   keeping a history of reads on the file, and tries to maintain a

   high-water mark on read ahead, which is always a certain delta from

   the most recent read.

 - More importantly, the Cache Manager reads further ahead for

   sequential access files--currently about three times more than

   files that are currently detected for sequential access.

If the caller makes multiple passes through a file, there are no negative

effects of specifying the sequential flag, because the Cache Manger will

still disable read ahead for as long as the application is getting hits on

the file (such as on the second or subsequent pass).

If you are working on an application where your ability to sequentially

read file data is key to performance, you may want to consider adding the

sequential flag to your create file call. This is especially true of

applications that use this flag to read from a CD-ROM.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: Noncontinuable Exceptions

Article ID: Q98840

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

An exception is noncontinuable if the event isn't continuable in the

hardware, or if continuation makes no sense. For example, if the caller's

stack is corrupted while trying to post an exception, continuing from the

bad stack exception would not be useful.

The noncontinuable exception does not terminate the application, and

therefore an application that can succeed in catching the exception and

running after a noncontinuable exception is free to do so. However, a

noncontinuable exception typically arises as a result of a corrupted stack

or other serious problem, making it very difficult to recover from the

exception.

Additional reference words: 3.10 non-continuable

KBCategory: Prg

KBSubcategory: BseExcept


INF: Validating User Account Passwords Under Windows NT

Article ID: Q98891

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Windows NT stores account names and passwords in the security accounts

manager (SAM) database. Windows NT checks this database to validate

passwords when users log on.

At this time, there is no nonprivileged service that takes a user name

and a password and returns an indication of whether or not the user

account password is valid. There is a privileged service that handles

this password validation; it is for use by logon processes such as

winlogon. This service is not yet published. A nonprivileged service

that will perform password validation is under consideration for the

versions of Windows NT that will follow the first released product.

MORE INFORMATION

================

The SAM application programming interface (API) functions were not

exposed due to their changing nature. Microsoft is working on a

developer's kit that will provide guidelines and tutorial information

about most of the security API functions, including the SAM APIs.

Exposing the SAM API will not compromise security because the

passwords are encrypted within SAM; they are one-way encrypted such

that not even SAM can decrypt them. Even a dictionary attack (encrypt

an entire dictionary and see if any of the words match) would not be

easy, because there is no SAM API function that will read the

encrypted password.

Additional reference words: 3.10 3.1 non-privileged

KBCategory: Prg

KBSubcategory: BseSecurity


PRB: Unexpected Result of SetFilePointer() with Devices

Article ID: Q98892

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

Open a floppy drive with CreateFile():

   h = CreateFile( "\\\\.\\a:", ... );

Use SetFilePointer() to advance the file pointer associated with the file

handle returned from CreateFile():

   SetFilePointer( h,    // file handle

                   5,    // distance (in bytes) to move file pointer

                NULL,    // optional high 32-bits of distance

          FILE_BEGIN     // specifies the starting point

   );

If the offset is not a multiple of the sector size of the floppy drive, the

function will return success; however, the pointer will not be exactly

where requested. The pointer value is rounded down to the beginning of the

sector that the pointer value is in.

CAUSE

=====

The behavior of this application programming interface (API) is by design

for the following reasons:

 - The I/O system is unaware of device particulars such as sector

   size; any offset is valid.

 - SetFilePointer() is very frequently used. Because speed is an

   important goal for Windows NT, time is not spent on querying

   device particulars and detecting such errors.

 - The logic to handle this situation is built into the file system,

   which actually performs the rounding, and therefore there was no

   need to put this into the code for SetFilePointer().

RESOLUTION

==========

When using SetFilePointer() with a handle that represents a floppy drive,

the offset must be a multiple of the sector size for the floppy drive in

order for the function to perform as expected.

MORE INFORMATION

================

Think of a file pointer as merely a stored value, which is where the next

read or write will take place. In fact, it is possible to override this

value on either the read or write itself, using certain APIs, by supplying

a different location. The new pointer location is remembered after the

operation. Therefore, the operation of "setting a file pointer" merely

means to go store a large integer in a cell in the system's data

structures, for possible use in the next file operation. In the case of a

handle to a device, the file pointer must be on a sector boundary.

In a similar way, ReadFile() only reads amounts that are multiples of the

sector size if it is passed a handle that represents a floppy drive.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: Limit on the Number of Bytes Written Asynchronously

Article ID: Q98893

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

There is a limit to the number of bytes that can be written with

WriteFile() using asynchronous I/O (FILE_FLAG_OVERLAPPED specified). This

limit depends on the size of your system.

Asynchronous (overlapped) I/O consumes system resources for a long time.

For example, the memory used is locked in the process working set until the

I/O completes. To limit the amount of system resources used asynchronously

by an application, the system charges asynchronous I/O to the working set

of the process requesting the I/O.

While the working set size is dynamically raised and lowered based on the

load, there are minimum and maximum values. These values are based on

system size: consider up to 12 megabytes (MB) a small system, between 12 MB

and 19 MB a medium system, and greater than 19 MB a large system. Each

process is guaranteed a minimum working set for performance reasons; about

120K for small systems, 160K for large systems, and 245K for large systems.

When system resources are heavily taxed, a process is confined to its

maximum working set. Asynchronous I/Os may never cause you to exceed your

maximum working set, because once you are allowed to initiate an

asynchronous I/O, the page cannot be taken away if memory becomes tight.

The maximum working set sizes are about 300K for a small system, 716K for a

medium system, and 1.5 MB for a large system.

MORE INFORMATION

================

The following code can be used to experiment with the maximum number of

bytes that can be written using asynchronous I/O. Simply change the line to

vary the number of bytes that the code attempts to write:

   #define NBR_BYTE 700000

Sample Code

-----------

#include <stdio.h>

#include <stdlib.h>

#include <malloc.h>

#include <assert.h>

#include <windows.h>

#define NBR_BYTE 700000

int main(void)

{

   char        *c;

   HANDLE      hFile;

   DWORD       byteWrite;

   OVERLAPPED  overLap;

   DWORD       err;

   BOOL        result;

   c = malloc( NBR_BYTE );

   assert( c != NULL );

   overLap.hEvent = CreateEvent( NULL, FALSE, FALSE, "event1" );

   assert( overLap.hEvent );

   hFile = CreateFile( "test", GENERIC_WRITE, 0,  NULL, OPEN_ALWAYS,

                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED |

                       FILE_FLAG_WRITE_THROUGH,

                       NULL);

   if( hFile == INVALID_HANDLE_VALUE )

   {

      free( c );

      printf( "error opening file\n" );

      exit( 0 );

   }

   overLap.Offset     = 0;

   overLap.OffsetHigh = 0;

   result = WriteFile( hFile, c, NBR_BYTE, &byteWrite, &overLap );

   if( result == FALSE )

   {

      err = GetLastError( );

      if( err != ERROR_IO_PENDING )

      {

         free( c );

         printf( "Error: %d\n", GetLastError() );

         exit( 0 );

      }

   }

   free( c );

   return 0;

}

Additional reference words: 3.10 asynch

KBCategory: Prg

KBSubcategory: BseFileio


INF: Setting File Permissions

Article ID: Q98952

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

In Windows NT, local access controls can be set on just NTFS partitions,

not FAT or HPFS partitions or floppies. Read/execute-only permissions

should work properly on a CD-ROM.

The exception is that ACLs (access control lists) can be set on shares,

regardless of the file system, to control access to all the files within

that share. For example, you can give read access to everyone, but give

full access just to members of a certain group or to certain individuals.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Possible Serial Baud Rates on Various Machines

Article ID: Q99026

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Computers running Windows NT may be unable to set the same serial baud

rates due to differences in serial port hardware on various platforms and

machines. These differences may be important to note when writing a serial

communications application that runs on different Windows NT platforms.

The simplest way to determine what baud rates are available on a particular

serial port is to call the GetCommProperties() application programming

interface (API) and examine the COMMPROP.dwSettableBaud bitmask to

determine what baud rates are supported on that serial port.

MORE INFORMATION

================

Some baud rates may be available on one machine and not on another because

of differences in the serial port hardware used on the two machines. Most

Intel 80x86 machines use a standard 1.8432 megahertz (MHz) clock speed on

serial port hardware, and therefore most Intel machines can set the same

baud rates. However, on other platforms, such as MIPS, there is no standard

serial port clock speed. MIPS serial ports are known to exist with 1.8432

MHz, 3.072 MHz, 4.2336 MHz, and 8.0 MHz serial port clock chips. Future NT

implementations on other platforms may have different serial port clock

speeds as well.

Furthermore, certain requested baud rates are special-cased in the Windows

NT serial driver so that they will work. The following are these special

cases:

   MHz     Requested Baud    Divisor   Resulting Baud Rate (+/- 1)

  ---------------------------------------------------------------

   1.8432      56000            2              57600

   3.072       14400           13              14769

   4.2336       9600           28               9450

   4.2336      14400           18              14700

   4.2336      19200           14              18900

   4.2336      38400            7              37800

   4.2336      56000            5              52920

   8.0         14400           35              14286

   8.0         56000            9              55556

The actual baud rate can be calculated by dividing the divisor multiplied

by 16 into the clock rate. For example, for a 1.8432 MHz clock and a

divisor of 2, the baud rate would be:

   1843200 Hz / (2 * 16) = 57600

For all other cases, as long as the requested baud rate is within 1 percent

of the nearest baud rate that can be found with an integer divisor, the

baud rate request will succeed.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCommapi


INF: Using GMEM_DDESHARE in Win32 Programming

Article ID: Q99114

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The GMEM_DDESHARE flag remains a legitimate value for GlobalAlloc(). This

flag can be used to indicate that the memory will be used for one of the

following so that the system can optimize the allocation for these special

needs:

   DDE

   OLE 1.0

   Clipboard operations

However, GlobalAlloc( GMEM_DDESHARE, ...) cannot be used to allocate a

block of memory that can be shared between processes. This flag was never

intended for this purpose, even under Windows versions 3.0 and 3.1 (3.x).

GlobalAlloc( GMEM_DDESHARE, ...) works in this case because all Windows 3.x

applications share the same address space; this is not the case under

Windows NT.

All allocations of global shared memory can be used within the process that

they are allocated in, but another mechanism is required to share memory

between processes.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMm


INF: Preventing the Console from Disappearing

Article ID: Q99115

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

When a console application is started from the File Manager, from the

Program Manager, or by typing "start <progname>" from the command prompt,

it executes in its own console. This console disappears as soon as the

application terminates, and therefore the user can't read anything written

to the screen between the last pause and program exit. To resolve this

problem, the programmer should pause the application before termination to

allow the user to read all of the information on the screen.

It is not likely that the programmer will want to introduce this pause if

the application is started directly from the command prompt, because in

this situation it won't make much sense to the user. However, there is no

API (application programming interface) that directly determines whether or

not the application shares a console with CMD.EXE. There is a method that

can be used to determine this information in most cases. When the

application first starts up, call GetConsoleScreenBufferInfo(). If the

cursor position is (0, 0), then the application has its own console, which

will disappear when the application terminates. Otherwise, the application

is operating within a console belonging to another program, typically

CMD.EXE.

NOTE: This method will not work if the user combines a clear screen (CLS)

and execution of the application into one step ([C:\] CLS & <progname>),

because the cursor position will be (0, 0), but the application is using

the console, which belongs to CMD.EXE.

MORE INFORMATION

================

To start a console application with its own console that will not disappear

when the application is terminated, use CMD /K. For example, use

   start CMD /K <progname>

Note that it is possible to programmatically force an application to always

have its own console by immediately doing a FreeConsole() and an

AllocConsole(). The disadvantage is that the C run-time handles are no

longer valid. Use CreateFile( "CONIN$", ... ) with lpsa->bInherit=TRUE, in

combination with _open_osfhandle() and dup2() to close the current handles

(stdin, stdout, stderr) and associate handles that will be inherited.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCon


INF: Types of File I/O Under Win32

Article ID: Q99173

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

There are multiple types of file handles that can be opened under Win32 and

the C Run-time:

   Returned Type  File Creation API      API Set

   ---------------------------------------------

   HANDLE         CreateFile()           Win32

   HFILE          OpenFile()/_lcreat()   Win32

   int            _creat()/_open()       C Run-time

   FILE *         fopen()                C Run-time

In general, these file I/O "families" are incompatible with each other. On

some implementations of the Win32 application programming interfaces

(APIs), the OpenFile()/_lcreat() family of file I/O APIs are implemented as

"wrappers" around the CreateFile() family of file I/O APIs, meaning that

OpenFile(), _lcreat(), and _lopen() end up calling CreateFile(), returning

the handle returned by CreateFile(), and do not maintain any state

information about the file themselves. However, this is an implementation

detail only and is NOT a design feature.

NOTE: You cannot count on this being true on other implementations of the

Win32 APIs. Win32 file I/O APIs may be written using different methods on

other platforms, so reliance on this implementation detail may cause your

application to fail.

The rule to follow is to use one family of file I/O APIs and stick with

them--do not open a file with _lopen() and read from it with ReadFile(),

for instance. This kind of incorrect use of the file I/O APIs can easily be

caught by the compiler, because the file types (HFILE and HANDLE

respectively) are incompatible with each other and the compiler will warn

you (at warning level /w3 or higher) when you have incorrectly passed one

type of file handle to a file I/O API that is expecting another, such as

passing an HFILE type to ReadFile(HANDLE, ...) in the above example.

MORE INFORMATION

================

Compatibility

-------------

The OpenFile() family of file I/O functions is provided only for

compatibility with earlier versions of Windows. New Win32 applications

should use the CreateFile() family of file I/O APIs, which provide added

functionality that the earlier file I/O APIs do not provide.

Each of the two families of C Run-time file I/O APIs are incompatible with

any of the other file I/O families. It is incorrect to open a file handle

with one of the C Run-time file I/O APIs and operate on that file handle

with any other family of file I/O APIs, nor can a C Run-time file I/O

family operate on file handles opened by any other file I/O family.

_get_osfhandle()

----------------

For the C Run-time unbuffered I/O family of APIs [_open(), and so forth],

it is possible to extract the operating system handle that is associated

with that C run-time handle via the _get_osfhandle() C Run-time API. The

operating system handle is the handle stored in a C Run-time internal

structure associated with that C Run-time file handle. This operating

system handle is the handle that is returned from an operating system call

made by the C Run-time to open a file [CreateFile() in this case] when you

call one of the C Run-time unbuffered I/O APIs [_open(), _creat(),

_sopen(), and so forth].

The _get_osfhandle() C Run-time call is provided for informational purposes

only. Problems may occur if you read or write to the file using the

operating system handle returned from _get_osfhandle(); for these reasons

we recommend that you do not use the returned handle to read or write to

the file.

It is also possible to construct a C Run-time unbuffered file I/O handle

from an operating system handle [a CreateFile() handle] with the

_open_osfhandle() C Run-time API. In this case, the C Run-time uses the

existing operating system handle that you pass in rather than opening the

file itself. It is possible to use the original operating system handle to

read or write to the file, but it is very important that you use only the

original handle or the returned C Run-time handle to access the file, but

not both, because the C Run-time maintains state information that will not

be updated if you use the operating system handle to read or write to the

file.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: Performing a Clear Screen (CLS) in a Console Application

Article ID: Q99261

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

There is no Win32 application programming interface (API) that will clear

the screen in a console application. However, it is fairly easy to write a

function that will programmatically clear the screen. The following

function is an example:

void cls( HANDLE hConsole )

{

   COORD coordScreen = { 0, 0 };    /* here's where we'll home the

                                       cursor */

   BOOL bSuccess;

   DWORD cCharsWritten;

   CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */

   DWORD dwConSize;                 /* number of character cells in

                                       the current buffer */

   /* get the number of character cells in the current buffer */

   bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );

   PERR( bSuccess, "GetConsoleScreenBufferInfo" );

   dwConSize = csbi.dwSize.X * csbi.dwSize.Y;

   /* fill the entire screen with blanks */

   bSuccess = FillConsoleOutputCharacter( hConsole, (TCHAR) ' ',

      dwConSize, coordScreen, &cCharsWritten );

   PERR( bSuccess, "FillConsoleOutputCharacter" );

   /* get the current text attribute */

   bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );

   PERR( bSuccess, "ConsoleScreenBufferInfo" );

   /* now set the buffer's attributes accordingly */

   bSuccess = FillConsoleOutputAttribute( hConsole, csbi.wAttributes,

      dwConSize, coordScreen, &cCharsWritten );

   PERR( bSuccess, "FillConsoleOutputAttribute" );

   /* put the cursor at (0, 0) */

   bSuccess = SetConsoleCursorPosition( hConsole, coordScreen );

   PERR( bSuccess, "SetConsoleCursorPosition" );

   return;

}

Additional reference words: 3.10 clearscreen

KBCategory: Prg

KBSubcategory: BseCon


INF: Win32 Equivalents for C Run-Time Functions

Article ID: Q99456

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Many of the C run-time functions have direct equivalents in the Win32

application programming interface (API). This article lists the C Run-time

functions by category with their Win32 equivalents or the word "none" if no

equivalent exists.

MORE INFORMATION

================

NOTE: the functions that are followed by an asterisk (*) are part of the 16-

bit C Run-time only. Functions that are unique to the 32-bit C Run-time are

listed separately in the last section. All other functions are common to

both C Run-times.

Buffer Manipulation

-------------------

   _memccpy                  none

    memchr                   none

    memcmp                   none

    memcpy                   CopyMemory

   _memicmp                  none

    memmove                  MoveMemory

    memset                   FillMemory, ZeroMemory

   _swab                     none

Character Classification

------------------------

     isalnum                 IsCharAlphaNumeric

     isalpha                 IsCharAlpha, GetStringTypeW (Unicode)

   __isascii                 none

     iscntrl                 none, GetStringTypeW (Unicode)

   __iscsym                  none

   __iscsymf                 none

     isdigit                 none, GetStringTypeW (Unicode)

     isgraph                 none

     islower                 IsCharLower, GetStringTypeW (Unicode)

     isprint                 none

     ispunct                 none, GetStringTypeW (Unicode)

     isspace                 none, GetStringTypeW (Unicode)

     isupper                 IsCharUpper, GetStringTypeW (Unicode)

     isxdigit                none, GetStringTypeW (Unicode)

   __toascii                 none

     tolower                 CharLower

    _tolower                 none

     toupper                 CharUpper

    _toupper                 none

Directory Control

-----------------

   _chdir                    SetCurrentDirectory

   _chdrive                  SetCurrentDirectory

   _getcwd                   GetCurrentDirectory

   _getdrive                 GetCurrentDirectory

   _mkdir                    CreateDirectory

   _rmdir                    RemoveDirectory

   _searchenv                SearchPath

File Handling

-------------

   _access                   none

   _chmod                    SetFileAttributes

   _chsize                   SetEndOfFile

   _filelength               GetFileSize

   _fstat                    See Note 5

   _fullpath                 GetFullPathName

   _get_osfhandle            none

   _isatty                   GetFileType

   _locking                  LockFileEx

   _makepath                 none

   _mktemp                   GetTempFileName

   _open_osfhandle           none

    remove                   DeleteFile

    rename                   MoveFile

   _setmode                  none

   _splitpath                none

   _stat                     none

   _umask                    none

   _unlink                   DeleteFile

Creating Text Output Routines

-----------------------------

   _displaycursor*           SetConsoleCursorInfo

   _gettextcolor*            GetConsoleScreenBufferInfo

   _gettextcursor*           GetConsoleCursorInfo

   _gettextposition*         GetConsoleScreenBufferInfo

   _gettextwindow*           GetConsoleWindowInfo

   _outtext*                 WriteConsole

   _scrolltextwindow*        ScrollConsoleScreenBuffer

   _settextcolor*            SetConsoleTextAttribute

   _settextcursor*           SetConsoleCursorInfo

   _settextposition*         SetConsoleCursorPosition

   _settextwindow*           SetConsoleWindowInfo

   _wrapon*                  SetConsoleMode

Stream Routines

---------------

    clearerr                 none

    fclose                   CloseHandle

   _fcloseall                none

   _fdopen                   none

    feof                     none

    ferror                   none

    fflush                   FlushFileBuffers

    fgetc                    none

   _fgetchar                 none

    fgetpos                  none

    fgets                    none

   _fileno                   none

   _flushall                 none

    fopen                    CreateFile

    fprintf                  none

    fputc                    none

   _fputchar                 none

    fputs                    none

    fread                    ReadFile

    freopen (std handles)    SetStdHandle

    fscanf                   none

    fseek                    SetFilePointer

    fsetpos                  SetFilePointer

   _fsopen                   CreateFile

    ftell                    SetFilePointer (check return value)

    fwrite                   WriteFile

    getc                     none

    getchar                  none

    gets                     none

   _getw                     none

    printf                   none

    putc                     none

    putchar                  none

    puts                     none

   _putw                     none

    rewind                   SetFilePointer

   _rmtmp                    none

    scanf                    none

    setbuf                   none

    setvbuf                  none

   _snprintf                 none

    sprintf                  wsprintf

    sscanf                   none

   _tempnam                  GetTempFileName

    tmpfile                  none

    tmpnam                   GetTempFileName

    ungetc                   none

    vfprintf                 none

    vprintf                  none

   _vsnprintf                none

    vsprintf                 wvsprintf

Low-Level I/O

-------------

   _close                   _lclose, CloseHandle

   _commit                   FlushFileBuffers

   _creat                   _lcreat, CreateFile

   _dup                      DuplicateHandle

   _dup2                     none

   _eof                      none

   _lseek                   _llseek, SetFilePointer

   _open                    _lopen, CreateFile

   _read                    _lread, ReadFile

   _sopen                    CreateFile

   _tell                     SetFilePointer (check return value)

   _write                   _lread

Console and Port I/O Routines

-----------------------------

   _cgets                    none

   _cprintf                  none

   _cputs                    none

   _cscanf                   none

   _getch                    ReadConsoleInput

   _getche                   ReadConsoleInput

   _inp                      none

   _inpw                     none

   _kbhit                    PeekConsoleInput

   _outp                     none

   _outpw                    none

   _putch                    WriteConsoleInput

   _ungetch                  none

Memory Allocation

-----------------

   _alloca                   none

   _bfreeseg*                none

   _bheapseg*                none

    calloc                   GlobalAlloc

   _expand                   none

    free                     GlobalFree

   _freect*                  GlobalMemoryStatus

   _halloc*                  GlobalAlloc

   _heapadd                  none

   _heapchk                  none

   _heapmin                  none

   _heapset                  none

   _heapwalk                 none

   _hfree*                   GlobalFree

    malloc                   GlobalAlloc

   _memavl                   GlobalMemoryStatus

   _memmax                   GlobalMemoryStatus

   _msize*                   GlobalSize

    realloc                  GlobalReAlloc

   _set_new_handler          none

   _set_hnew_handler*        none

   _stackavail*              none

Process and Environment Control Routines

----------------------------------------

    abort                    none

    assert                   none

    atexit                   none

   _cexit                    none

   _c_exit                   none

   _exec functions           none

    exit                     ExitProcess

   _exit                     ExitProcess

    getenv                   GetEnvironmentVariable

   _getpid                   GetCurrentProcessId

    longjmp                  none

   _onexit                   none

    perror                   FormatMessage

   _putenv                   SetEnvironmentVariable

    raise                    RaiseException

    setjmp                   none

    signal (ctrl-c only)     SetConsoleCtrlHandler

   _spawn functions          CreateProcess

    system                   CreateProcess

String Manipulation

-------------------

   strcat, wcscat            lstrcat

   strchr, wcschr            none

   strcmp, wcscmp            lstrcmp

   strcpy, wcscpy            lstrcpy

   strcspn, wcscspn          none

  _strdup, _wcsdup           none

   strerror                  FormatMessage

  _strerror                  FormatMessage

  _stricmp, _wcsicmp         lstrcmpi

   strlen, wcslen            lstrlen

  _strlwr, _wcslwr           CharLower, CharLowerBuffer

   strncat, wcsncat          none

   strncmp, wcsncmp          none

   strncpy, wcsncpy          none

  _strnicmp, _wcsnicmp       none

  _strnset, _wcsnset         FillMemory, ZeroMemory

   strpbrk, wcspbrk          none

   strrchr, wcsrchr          none

  _strrev, _wcsrev           none

  _strset, _wcsset           FillMemory, ZeroMemory

   strspn, wcsspn            none

   strstr, wcsstr            none

   strtok, wcstok            none

  _strupr, _wcsupr           CharUpper, CharUpperBuffer

MS-DOS Interface

----------------

  _bdos*                     none

  _chain_intr*               none

  _disable*                  none

  _dos_allocmem*             GlobalAlloc

  _dos_close*                CloseHandle

  _dos_commit*               FlushFileBuffers

  _dos_creat*                CreateFile

  _dos_creatnew*             CreateFile

  _dos_findfirst*            FindFirstFile

  _dos_findnext*             FindNextFile

  _dos_freemem*              GlobalFree

  _dos_getdate*              GetSystemTime

  _dos_getdiskfree*          GetDiskFreeSpace

  _dos_getdrive*             GetCurrentDirectory

  _dos_getfileattr*          GetFileAttributes

  _dos_getftime*             GetFileTime

  _dos_gettime*              GetSystemTime

  _dos_getvect*              none

  _dos_keep*                 none

  _dos_open*                 OpenFile

  _dos_read*                 ReadFile

  _dos_setblock*             GlobalReAlloc

  _dos_setdate*              SetSystemTime

  _dos_setdrive*             SetCurrentDirectory

  _dos_setfileattr*          SetFileAttributes

  _dos_setftime*             SetFileTime

  _dos_settime*              SetSystemTime

  _dos_setvect*              none

  _dos_write*                WriteFile

  _dosexterr*                GetLastError

  _enable*                   none

  _FP_OFF*                   none

  _FP_SEG*                   none

  _harderr*                  See Note 1

  _hardresume*               See Note 1

  _hardretn*                 See Note 1

  _int86*                    none

  _int86x*                   none

  _intdos*                   none

  _intdosx*                  none

  _segread*                  none

Time

----

   asctime                   See Note 2

   clock                     See Note 2

   ctime                     See Note 2

   difftime                  See Note 2

   _ftime                    See Note 2

   _getsystime               GetDateAndTime

   gmtime                    See Note 2

   localtime                 See Note 2

   mktime                    See Note 2

   _strdate                  See Note 2

   _strtime                  See Note 2

   time                      See Note 2

   _tzset                    See Note 2

   _utime                    SetDateAndTimeFile

Virtual Memory Allocation

-------------------------

   _vfree*                   See Note 3

   _vheapinit*               See Note 3

   _vheapterm*               See Note 3

   _vload*                   See Note 3

   _vlock*                   See Note 3

   _vlockcnt*                See Note 3

   _vmalloc*                 See Note 3

   _vmsize*                  See Note 3

   _vrealloc*                See Note 3

   _vunlock*                 See Note 3

32-Bit C Run Time

------------------

   _beginthread              CreateThread

   _cwait                    WaitForSingleObject w/ GetExitCodeProcess

   _endthread                ExitThread

   _findclose                FindClose

   _findfirst                FindFirstFile

   _findnext                 FindNextFile

   _futime                   SetFileTime

   _get_osfhandle            none

   _open_osfhandle           none

   _pclose                   See Note 4

   _pipe                     CreatePipe

   _popen                    See Note 4

NOTE 1: The _harderr functions do not exist in the Win32 API. However, much

of their functionality is available through structured exception handling.

NOTE 2: The time functions are based on a format that is not used in Win32.

There are specific Win32 time functions that are documented in the Help

file.

NOTE 3: The virtual memory functions listed in this document are specific

to the MS-DOS environment and were written to access memory beyond the 640K

of RAM available in MS-DOS. Because this limitation does not exist in

Win32, the standard memory allocation functions should be used.

NOTE 4: While _pclose() and _popen() do not have direct Win32 equivalents,

you can (with some work) simulate them with the following calls:

   _popen                     CreatePipe

                              CreateProcess

   _pclose                    WaitForSingleObject

                              CloseHandle

NOTE 5: GetFileInformationByHandle() is the Win32 equivalent for the

_fstat() C Run-time function. However, GetFileInformationByHandle() is not

supported by Win32s version 1.1. It will be supported in Win32s 1.2.

GetFileSize(), GetFileAttributes(), GetFileTime(), and GetFileTitle() are

supported by Win32s.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


SAMPLE: Code Demonstration to Put a DACL on Floppy Disk Drives

Article ID: Q99459

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

There is no procedure for putting a discretionary access control list

(DACL) on floppy disk drives or COM ports with REGEDT32, using the Control

Panel, or using another part of the user interface. Furthermore, there is

no procedure for using the Win32 API to put a DACL that survives reboots

onto floppy disk drives or COM ports.

However, SD_FLPPY.EXE puts DACLs that survive logoff/logon on floppy disk

drives or COM ports; that is, these DACLs are on the floppy disk drives or

the COM ports until the next reboot.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

A version of this sample program can be installed as a service such that

each time the machine starts, the DACLs are automatically re-applied.

Purpose of This Sample

----------------------

The purpose of this sample is to show sample code that applies DACLs to

floppy disk drives or COM ports.

NOTE: There may be as many desired user interfaces to this sort of

functionality as there are people thinking about this, so it is not a

purpose of this sample (or the Win32 service variation of it) to present an

incredibly cool user interface to how the DACLs get applied. A very

simplistic approach is taken to the user interface. Anyone who wants more

complicated DACLs applied, or wants other variations in the user interface,

will probably benefit by being able to use this sample code as a starting

point for their DACL-applying application.

This is not a supported utility.

To Run

------

Type sd_flppy to lock the \\.\A: and \\.\B: devices.

Putting SD_FLPPY.EXE in a startup group or logon script might work for some

people.

The version of this program that is packaged as a Win32 service is in this

same directory and is built with SD_FLPPY.EXE by the same makefile.

The packaged-as-a-service approach might better suit people who need to

change the DACL on the floppy disk drives without requiring a reboot or

logoff. After installing the FLPSDSRV.EXE service on the machine, the

client application CHGFLPSD.EXE can be used over the network to lock,

unlock, or query the locked state of the floppy disk drives of any machine

where the FLPSDSRV.EXE service is running.

This packaged-as-a-service approach might better suit people that want to

inquire over the net what DACLs are on the floppy disk drives of particular

machines (to check or audit them). And this approach might better suit

people who would prefer that the DACLs be applied as the system boots up so

that the DACLs are applied before any user has logged on at the keyboard.

The packaged-as-a-service approach is useful for protecting the floppy disk

drives as a resource on a particular machine (regardless of who, if anyone,

is logged on); whereas, the SD_FLPPY.EXE approach (running an .EXE at logon

time) is useful for keeping a particular user from using the floppy disk

drives on any machine that that user might use. However, once user Sam6 has

logged on to machine \\Mach3 and locked the floppy disk drives with

SD_FLPPY.EXE, the floppy disk drives will stay locked until reboot. Of

course a utility could easily be written that could run in the startup

group of a different authorized user such as Jane3 to force the floppy disk

drives on any machine Jane3 logs on to to be unlocked.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam BseSecurity


SAMPLE: A Simple Service

Article ID: Q99460

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

The sample named SIMPLE demonstrates how to create and install a service.

In this particular case, the service merely opens a named pipe,

\\.\PIPE\SIMPLE, and waits for traffic. If the service receives anything,

it surrounds the input with

   Hello! [<input goes here>]

and sends it back down the pipe to the client.

The service can be started, stopped, paused, and continued.

To install the service, first compile everything, and then use INSTSRV to

install SimpleService as follows:

   instsrv SimpleService <location of SIMPLE.EXE>

To start the service, use either the "net start" method or use the Control

Panel Services application.

Once the service has been started, you can use the CLIENT program to verify

that the service is working correctly by using the following syntax:

   client \\.\pipe\simple stuff

This should return the response:

    Hello! [stuff]

After using the sample, if you want to remove the service, just type:

   instsrv SimpleService remove

NOTE: INSTSRV can be cause problems; it can install and remove any service

you tell it to, so be careful.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

Additional reference words: 3.10 CloseServiceHandle

InitializeSecurityDescriptor SetSecurityDescriptorDacl SetServiceStatus

OpenSCManager StartServiceCtrlDispatcher RegisterEventSource

DeregisterEventSource RegisterServiceCtrlHandler

KBCategory: Ref

KBSubcategory: CodeSam BseService


INF: FILE_FLAG_WRITE_THROUGH and FILE_FLAG_NO_BUFFERING

Article ID: Q99794

-----------------------------------------------------------------------

The information in this article applies to:

   - Microsoft Win32 Software Development Kit (SDK) for Windows NT

     version 3.1

-----------------------------------------------------------------------

SUMMARY

=======

The FILE_FLAG_WRITE_THROUGH flag for CreateFile() causes any writes made to

that handle to be written directly to the file without being buffered. The

data is cached (stored in the disk cache); however, it is still written

directly to the file. This method allows a read operation on that data to

satisfy the read request from cached data (if it's still there), rather

than having to do a file read to get the data. The write call doesn't

return until the data is written to the file. This applies to remote writes

as well--the network redirector passes the FILE_FLAG_WRITE_THROUGH flag to

the server so that the server knows not to satisfy the write request until

the data is written to the file.

The FILE_FLAG_NO_BUFFERING takes this concept one step further and

eliminates all read-ahead file buffering and disk caching as well, so that

all reads are guaranteed to come from the file and not from any system

buffer or disk cache. When using FILE_FLAG_NO_BUFFERING, disk reads and

writes must be done on sector boundaries, and buffer addresses must be

aligned on disk sector boundaries in memory.

These restrictions are necessary because the buffer that you pass to the

read or write API is used directly for I/O at the device level; at that

level, your buffer addresses and sector sizes must satisfy any processor

and media alignment restrictions of the hardware you are running on.

MORE INFORMATION

================

If you have a situation where you want to flush all open files on the

current logical drive, this can be done by:

   hFile = CreateFile("\\\\.\\c:", ....);

   FlushFileBuffers(hFile);

This method causes all buffered write data for all open files on the C:

partition to be flushed and written to the disk. Note that any buffering

done by anything other than the system is not affected by this flush; any

possible file buffering that the C Run-time is doing on files opened with C

Run-time routines is unaffected.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileiio


PRB: SetConsoleOutputCP() Not Functional

Article ID: Q99795

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

SetConsoleOutputCP() apparently has no effect.

CAUSE

=====

SetConsoleOutputCP() was designed to change the mapping of the 256 8-bit

character values into the glyph set of a fixed-pitch Unicode font, rather

than loading a separate, non-Unicode font for each call to

SetConsoleOutputCP(). Unfortunately, a fixed-pitch Unicode font was not

available by release time, so you can't view the effects of the

SetConsoleOutputCP() application programming interface (API) because the

currently available console fonts are not Unicode fonts.

STATUS

======

Microsoft has confirmed this to be a limitation in Windows NT version 3.1.

We will post new information here in the Microsoft Knowledge Base as it

becomes available.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCon


INF: Direct Drive Access Under Win32

Article ID: Q100027

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

To open a physical hard drive for direct disk access (raw I/O) in a Win32

application, use a device name of the form

   \\.\PhysicalDriveN

where N is 0, 1, 2, and so forth, representing each of the physical drives

in the system.

To open a logical drive, direct access is of the form

   \\.\X:

where X: is a hard-drive partition letter, floppy disk drive, or CD-ROM

drive.

MORE INFORMATION

================

You can open a physical or logical drive using the CreateFile() application

programming interface (API) with these device names provided that you have

the appropriate access rights to the drive (that is, you must be an

administrator). You must use both the CreateFile() FILE_SHARE_READ and

FILE_SHARE_WRITE flags to gain access to the drive.

Once the logical or physical drive has been opened, you can then perform

direct I/O to the data on the entire drive. When performing direct disk

I/O, you must seek, read, and write in multiples of sector sizes of the

device and on sector boundaries. Call DeviceIoControl() using

IOCTL_DISK_GET_DRIVE_GEOMETRY to get the bytes per sector, number of

sectors, sectors per track, and so forth, so that you can compute the size

of the buffer that you will need.

Note that a Win32 application cannot open a file by using internal Windows

NT object names; for instance, attempting to open a CD-ROM drive by opening

   \Device\CdRom0

does not work because this is not a valid Win32 device name. An application

can use the QueryDosDevice() API to get a list of all valid Win32 device

names and see the mapping between a particular Win32 device name and an

internal Windows NT object name. An application running at a sufficient

privilege level can define, redefine, or delete Win32 device mappings by

calling the DefineDosDevice() API.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: Restriction on Named-Pipe Names

Article ID: Q100291

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

Named pipes are implemented in Windows NT using the same approach used for

file systems. Within Windows NT, named pipes are represented as file

objects.

During the design phase, one idea for the implementation was to allow

subdirectories of named pipes. For example, a developer could create a

named pipe subdirectory called \MYPIPES. It would then be possible to

create and use pipes called \MYPIPES\PIPE1 and \MYPIPES\PIPE2, but it would

not be possible to use \MYPIPES as a pipe.

In the end, this idea was not implemented, so subdirectories are not

supported. This does have some effect on the named-pipe names that are

allowed. If a pipe named \MYPIPES is created, it is not possible to

subsequently create a pipe named \MYPIPES\PIPE1, because \MYPIPES is

already a pipe name and cannot be used as a subdirectory. It is possible to

create a pipe named \MYPIPES\PIPE1, but only if there is no pipe named

\MYPIPES.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseIpc


INF: Replacing the Shell (Program Manager)

Article ID: Q100328

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

To replace the current shell, change the following registry key:

   HKEY_LOCAL_MACHINE\

      SOFTWARE\

      MICROSOFT\

      Windows NT\

      Current Version\

      Winlogon\

      Shell

Note that Program Manager combines the functionality of Program Manager and

Task Manager (the Task Manager installed is not actually run). Therefore,

if the new shell does not replace the Task Manager functionality, the

replacement string should contain both the new shell name and TASKMAN.EXE,

separated by commas.

To update the string that is retrieved when calling

GetPrivateProfileString(), change the string in the following registry key:

   HKEY_LOCAL_MACHINE\

      SOFTWARE\

      MICROSOFT\

      Windows NT\

      Current Version\

      WOW\

      Boot\

      Shell

The duplicate entry is for compatibility with Windows 3.1.

MORE INFORMATION

================

WritePrivateProfileString() changes the following registry key:

   HKEY_LOCAL_MACHINE\

      SOFTWARE\

      MICROSOFT\

      Windows NT\

      Current Version\

      WOW\

      Boot\

      Shell

It does not have the desired effect of actually changing the Shell.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: CPU Quota Limits Not Enforced

Article ID: Q100329

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

On page 88 of "Inside Windows NT," Table 4-1 indicates that a process

object contains a quota limit for the maximum amount of processor time that

the process can use.

This limit is not enforced in Windows NT version 3.1.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Time Stamps Under the FAT File System

Article ID: Q101186

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

Windows NT considers the time stamp on a file stored on a FAT (file

allocation table) partition to be standard time if the current time is

standard time, and daylight time if the current time is daylight time,

regardless of what time of year the file was originally time stamped.

This is not an issue under NTFS, which consistently implements Universal

Coordinated Time.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: Examining the dwOemId Value

Article ID: Q101190

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

The Win32 application programming interface (API) GetSystemInfo() fills in

the members of a SYSTEM_INFO structure. The dwOemId member represents a

computer identifier that is specific to a particular OEM (original

equipment manufacturer). The first version of Windows NT always places a

zero in the dwOemId member. In a later release, this behavior will change

to include different OEM IDs.

Additional reference words: 3.10

KBCategory:

KBSubcategory: BseMisc


INF: Interrupting Threads in Critical Sections

Article ID: Q101193

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

If a thread enters a critical section and then terminates abnormally, the

critical section object will not be released. Many components of the C

Run-time library are not reentrant and use a resource locking scheme to

maintain coherency in the multithreaded environment. Thus, a thread that

has entered a C Run-time function, such as printf(), could deadlock all

access (within that process) to printf() if it terminates abnormally.

This situation could arise if a thread is terminated with TerminateThread()

while it holds a resource lock. If this occurs, any thread that tries to

acquire that resource lock will become deadlocked.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Changes to DLL Makefiles for Windows NT 3.1 Release

Article ID: Q101337

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The documentation and sample makefiles for beta versions of the Win32

software development kit (SDK) use a different entry point for dynamic-link

libraries (DLLs) than is recommended for the Windows NT 3.1 release. This

difference is especially important to note if your DLLs are linked with the

C Run-time.

Previously, Microsoft recommended calling _crt_init() in your DLL entry

point (or making it the DLL entry point), so that the C run time would be

correctly initialized. Currently, Microsoft recommends that all DLLs

provide a main function

   BOOL WINAPI DllMain( HANDLE hDLL, DWORD dwReason, LPVOID lpReserved )

and that the entry point be specified with the following linker

option:

   -entry:_DllMainCRTStartup$(DLLENTRY)

MORE INFORMATION

================

The loader calls DllMainCRTStartup(), which is provided in the C Run-time

library. This routine handles all C Run-time and C++ initialization, then

determines whether DllMain() is exported from the DLL, and executes it if

it exists.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseDll


INF: Impersonation Provided by ImpersonateNamedPipeClient()

Article ID: Q101378

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The following information is from the Win32 application programming

interface (API) "Programmer's Reference" in the section regarding

ImpersonateNamedPipeClient():

   BOOL ImpersonateNamedPipeClient(HANDLE hNamedPipe)

   The ImpersonateNamedPipeClient function impersonates a named-pipe

   client application.

The level of impersonation can be specified by the client when the named

pipe is opened. If the client does not explicitly specify a level, then the

default is SecurityImpersonation.

MORE INFORMATION

================

Suppose there are three threads (A, B, and C) where:

   A calls B

   B calls C

   B does a SecurityImpersonation of A

If A and B both specify dynamic tracking, then C can see the context of A

when it makes a call on the pipe, as long as B impersonates A. Otherwise, C

will see the context of A only if B was impersonating A when the pipe

between B and C was connected.

Note that dynamic tracking is not supported between machines.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Application Exception Error Codes

Article ID: Q101774

--------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

--------------------------------------------------------------------

Many exception errors are not processed by applications. The most common

exception error is EXCEPTION_ACCESS_VIOLATION (c0000005). It occurs when a

pointer is dereferenced and the pointer points to inaccessible memory or a

write operation is attempted on read-only memory. If an application does

not trap an exception, the Win32 module, UnhandledExceptionFilter, will do

one of the following: display a message box, invoke Dr. Watson, or attach

your application to a debugger.

The following are standard exception errors:

   EXCEPTION_ACCESS_VIOLATION

   EXCEPTION_ARRAY_BOUNDS_EXCEEDED

   EXCEPTION_BREAKPOINT

   EXCEPTION_DATATYPE_MISALIGNMENT

   EXCEPTION_FLT_DENORMAL_OPERAND

   EXCEPTION_FLT_DIVIDE_BY_ZERO

   EXCEPTION_FLT_INEXACT_RESULT

   EXCEPTION_FLT_INVALID_OPERATION

   EXCEPTION_FLT_OVERFLOW

   EXCEPTION_FLT_STACK_CHECK

   EXCEPTION_FLT_UNDERFLOW

   EXCEPTION_ILLEGAL_INSTRUCTION

   EXCEPTION_IN_PAGE_ERROR

   EXCEPTION_INT_DIVIDE_BY_ZERO

   EXCEPTION_INT_OVERFLOW

   EXCEPTION_INVALID_DISPOSITION

   EXCEPTION_NONCONTINUABLE_EXCEPTION

   EXCEPTION_PRIV_INSTRUCTION

   EXCEPTION_SINGLE_STEP

   EXCEPTION_STACK_OVERFLOW

Additional reference words: 3.10

KBCategory: Prg

KBSubCategory: BseExcept


INF: Gaining Access to ACLs

Article ID: Q102098

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

To gain access to a security access control list (SACL), a process must

have the SE_SECURITY_NAME privilege. When requesting access, the calling

process must request ACCESS_SYSTEM_SECURITY in the desired access mask.

There is not a privilege that controls read or write access to a

discretionary access control list (DACL). Instead, access to read and write

an object's DACL is granted by the READ_CONTROL and WRITE_DAC access

rights, respectively. These rights must be specifically granted to the user

(or group containing the user) for DACL read or write access to be granted.

If the owner of an object requests READ_CONTROL or WRITE_DAC, the access

will always be granted.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Administrator Access to Files

Article ID: Q102099

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

A user that is a member of the Administrator group is not automatically

granted access to any file on the local machine. For an administrator to

access a file, permission must be specifically granted (as for any user) in

the file's discretionary access control list (DACL).

If an administrator wants to access a file that he or she is not granted

access to, the administrator must first take ownership of that file. Once

ownership is taken, the administrator will have full access to the file. It

is important to note that administrator cannot give ownership back to the

original owner. If this were so, the administrator could take ownership of

a file, examine it, and then assign it back to the original owner without

that owner's knowledge.

NOTE: Because administrators have backup privileges, an administrator could

back up a file (or entire volume) and restore it onto another system. The

administrator could then take ownership of a file on this new system

without the owner's knowledge. Please keep this in mind when thinking about

file security.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Passing Security Information to SetFileSecurity()

Article ID: Q102100

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The SetFileSecurity() Win32 application programming interface (API) takes a

pointer to a Security Descriptor. This is because SetFileSecurity() can set

any of the following security information for a file:

   The owner identifier of the file

   The primary group identifier of the file

   The discretionary access-control list (DACL) of the file

   The system access-control list (SACL) of the file

When you pass the SD and SECURITY_INFORMATION structure to

SetFileSecurity(), the SECURITY_INFORMATION structure identifies which

security information is to be set. The SECURITY_INFORMATION structure is a

DWORD that can be one of the following values:

   OWNER_SECURITY_INFORMATION

   GROUP_SECURITY_INFORMATION

   DACL_SECURITY_INFORMATION

   SACL_SECURITY_INFORMATION

Each of these values represents one of the security items listed above. The

SD that is passed to SetFileSecurity() is simply a container for the

security information being set for the specified file. SetFileSecurity()

examines the value in the SECURITY_INFORMATION structure, extracts the

appropriate information from the provided SD, and applies it to the

specified file's SD.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Extracting the SID from an ACE

Article ID: Q102101

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

To access the security identifier (SID) contained in an access control

entry (ACE), the following syntax can be used:

   PSID pSID;

   if((((PACE_HEADER)pTempAce)->AceType) == ACCESS_ALLOWED_ACE_TYPE)

   {

      pSID=(PSID)&((PACCESS_ALLOWED_ACE)pTempAce)->SidStart;

   }

MORE INFORMATION

================

The "if" statement checks the type of ACE, which is one of the following

values:

   ACCESS_ALLOWED_ACE_TYPE

   ACCESS_DENIED_ACE_TYPE

   SYSTEM_AUDIT_ACE_TYPE

The conditional statement casts pTempAce (the pointer to the ACE) to a

PACCESS_ALLOWED_ACE structure. The address of the SidStart member is then

cast to a PSID and assigned to the pSID variable. pSID can now be used with

any Win32 Security application programming interface (API) that takes a

PSID as a parameter.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: How to Add an Access-Allowed ACE to a File

Article ID: Q102102

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

This article explains the process of adding an access-allowed (or

access-denied) access control entry (ACE) to a file.

Adding an access-allowed ACE to a file's access control list (ACL) provides

a means of granting or denying (using an access-denied ACE) access to the

file to a particular user or group. In most cases, the file's ACL will not

have enough free space to add an additional ACE, and therefore it is

usually necessary to create a new ACL and copy the file's existing ACEs

over to it. Once the ACEs are copied over and the access-allowed ACE is

also added, the new ACL can be applied to the file's security descriptor

(SD). This process is explained in detail in the section below. Sample code

is provided at the end of this article.

MORE INFORMATION

================

At the end of this article is sample code that defines a function named

AddAccessRights(), which adds an access-allowed ACE to the specified file

allowing the specified access. Steps 1-17 in the comments of the sample

code are discussed in detail below:

 1. GetUserName() is called to retrieve the name of the currently

    logged in user. The user name is stored in plszUserName[] array.

 2. LookupAccountName() is called to obtain the SID of the user

    returned by GetUserName() in step 1. The resulting SID is stored

    in the UserSID variable and will be used later in the

    AddAccessAllowedACE() application programming interface (API)

    call. The LookupAccountName() API is also providing the user's

    domain in the plszDomain[] array. Please note that

    LookupAccountName() returns the SID of the first user or group

    that matches the name in plszUserName.

 3. GetFileSecurity() is used here to obtain a copy of the file's

    security descriptor (SD). The file's SD is placed into the ucSDbuf

    variable, which is declared a size of

    65536+SECURITY_DESCRIPTOR_MIN_LENGTH for simplicity. This value

    represents the maximum size of an SD, which ensures the SD will be

    of sufficient size.

 4. Here we initialize the new security descriptor (NewSD variable) by

    calling the InitializeSecurityDescriptor() API. Because the

    SetFileSecurity() API requires that the security item being set is

    contained in a SD, we create and initialize NewSD.

 5. Here GetSecurityDescriptorDacl() retrieves a pointer to the

    discretionary access control list (DACL) in the SD. The pointer is

    stored in the pACL variable.

 6. GetAclInformation() is called here to obtain size information on

    the file's DACL in the form of a ACL_SIZE_INFORMATION structure.

    This information is used when computing the size of the new DACL

    and when copying ACEs.

 7. This statement computes the exact number of bytes to allocate for

    the new DACL. The AclBytesInUse member represents the number of

    bytes being used in the file's DACL. We add this number to the

    size of an ACCESS_ALLOWED_ACE and the size of the user's SID.

    Subtracting the size of a DWORD is an adjustment required to

    obtain the exact number of bytes necessary.

 8. Here we allocate memory for the new ACL that will ultimately

    contain the file's existing ACEs plus the access-allowed ACE.

 9. In addition to allocating the memory, it is important to

    initialize the ACL structure as we do here.

10. Here we check the bDaclPresent flag returned by

    GetSecurityDescriptorDacl() to see if a DACL was present in the

    file's SD. If a DACL was not present, then we skip the code that

    copies the file's ACEs to the new DACL.

11. After verifying that there is at least one ACE in the file's DACL

    (by checking the AceCount member), we begin the loop to copy the

    individual ACEs to the new DACL.

12. Here we get a pointer to an ACE in the file's DACL by using the

    GetAce() API.

13. Now we add the ACE to the new DACL. It is important to note that

    we pass MAXDWORD for the dwStartingAceIndex parameter of AddAce()

    to ensure the ACE is added to the end of the DACL. The statement

    ((PACE_HEADER)pTempAce)->AceSize provides the size of the ACE.

14. Now that we have copied all the file's original ACEs over to our

    new DACL, we add the access-allowed ACE. The dwAccessMask variable

    will contain the access mask being granted. GENERIC_READ is an

    example of an access mask.

15. Because the SetFileSecurity() API can set a variety of security

    information, it takes a pointer to a security descriptor. For this

    reason, it is necessary to attach our new DACL to a temporary SD.

    This is done by using the SetSecurityDescriptorDacl() API.

16. Now that we have a SD containing the new DACL for the file, we set

    the DACL to the file's SD by calling SetFileSecurity(). The

    DACL_SECURITY_INFORMATION parameter indicates that we want the

    DACL in the provided SD applied to the file's SD. Please note that

    only the file's DACL is set, the other security information in the

    file's SD remains unchanged.

17. Here we free the memory that was allocated for the new DACL.

The below sample demonstrates the basic steps required to add an access-

allowed ACE to a file's DACL. Please note that this same process can be

used to add an access-denied ACE to a file's DACL. Because the access-

denied ACE should appear before access-allowed ACEs, it is suggested that

the call to AddAccessDeniedAce() precede the code that copies the existing

ACEs to the new DACL.

Sample Code

-----------

#define SD_SIZE (65536 + SECURITY_DESCRIPTOR_MIN_LENGTH)

BOOL AddAccessRights(CHAR *pFileName, DWORD dwAcessMask)

{

   // SID variables

   UCHAR          psnuType[2048];

   UCHAR          lpszDomain[2048];

   DWORD          dwDomainLength = 250;

   UCHAR          UserSID[1024];

   DWORD          dwSIDBufSize=1024;

   // User name variables

   UCHAR          lpszUserName[250];

   DWORD          dwUserNameLength = 250;

   // File SD variables

   UCHAR          ucSDbuf[SD_SIZE];

   PSECURITY_DESCRIPTOR pFileSD=(PSECURITY_DESCRIPTOR)ucSDbuf;

   DWORD          dwSDLengthNeeded;

   // ACL variables

   PACL           pACL;

   BOOL           bDaclPresent;

   BOOL           bDaclDefaulted;

   ACL_SIZE_INFORMATION AclInfo;

   // New ACL variables

   PACL           pNewACL;

   DWORD          dwNewACLSize;

   // New SD variables

   UCHAR                NewSD[SECURITY_DESCRIPTOR_MIN_LENGTH];

   PSECURITY_DESCRIPTOR psdNewSD=(PSECURITY_DESCRIPTOR)NewSD;

   // Temporary ACE

   PVOID          pTempAce;

   UINT           CurrentAceIndex;

   // STEP 1: Get the logged on user name

   if(!GetUserName(lpszUserName,&dwUserNameLength))

   {

      printf("Error %d:GetUserName\n",GetLastError());

      return(FALSE);

   }

   // STEP 2: Get SID for current user

   if (!LookupAccountName((LPSTR) NULL,

       lpszUserName,

       UserSID,

       &dwSIDBufSize,

       lpszDomain,

       &dwDomainLength,

       (PSID_NAME_USE)psnuType))

   {

      printf("Error %d:LookupAccountName\n",GetLastError());

      return(FALSE);

   }

   // STEP 3: Get security descriptor (SD) for file

   if(!GetFileSecurity(pFileName,

                 (SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION),

                 pFileSD,

                 SD_SIZE,

                 (LPDWORD)&dwSDLengthNeeded))

   {

      printf("Error %d:GetFileSecurity\n",GetLastError());

      return(FALSE);

   }

   // STEP 4: Initialize new SD

   if(!InitializeSecurityDescriptor(psdNewSD,SECURITY_DESCRIPTOR_REVISION))

   {

      printf("Error %d:InitializeSecurityDescriptor\n",GetLastError());

      return(FALSE);

   }

   // STEP 5: Get DACL from SD

   if (!GetSecurityDescriptorDacl(pFileSD,

                    &bDaclPresent,

                    &pACL,

                    &bDaclDefaulted))

   {

      printf("Error %d:GetSecurityDescriptorDacl\n",GetLastError());

      return(FALSE);

   }

   // STEP 6: Get file ACL size information

   if(!GetAclInformation(pACL,&AclInfo,sizeof(ACL_SIZE_INFORMATION),

      AclSizeInformation))

   {

      printf("Error %d:GetAclInformation\n",GetLastError());

      return(FALSE);

   }

   // STEP 7: Compute size needed for the new ACL

   dwNewACLSize = AclInfo.AclBytesInUse +

                  sizeof(ACCESS_ALLOWED_ACE) +

                  GetLengthSid(UserSID) - sizeof(DWORD);

   // STEP 8: Allocate memory for new ACL

   pNewACL = (PACL)LocalAlloc(LPTR, dwNewACLSize);

   // STEP 9: Initialize the new ACL

   if(!InitializeAcl(pNewACL, dwNewACLSize, ACL_REVISION2))

   {

      printf("Error %d:InitializeAcl\n",GetLastError());

      LocalFree((HLOCAL) pNewACL);

      return(FALSE);

   }

   // STEP 10: If DACL is present, copy it to a new DACL

   if(bDaclPresent)  // only copy if DACL was present

   {

      // STEP 11: Copy the file's ACEs to our new ACL

      if(AclInfo.AceCount)

      {

         for(CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount;

            CurrentAceIndex++)

         {

            // STEP 12: Get an ACE

            if(!GetAce(pACL,CurrentAceIndex,&pTempAce))

            {

              printf("Error %d: GetAce\n",GetLastError());

              LocalFree((HLOCAL) pNewACL);

              return(FALSE);

            }

             // STEP 13: Add the ACE to the new ACL

            if(!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,

               ((PACE_HEADER)pTempAce)->AceSize))

            {

               printf("Error %d:AddAce\n",GetLastError());

               LocalFree((HLOCAL) pNewACL);

               return(FALSE);

            }

          }

      }

   }

   // STEP 14: Add the access-allowed ACE to the new DACL

   if(!AddAccessAllowedAce(pNewACL,ACL_REVISION2,dwAcessMask, &UserSID))

   {

      printf("Error %d:AddAccessAllowedAce",GetLastError());

      LocalFree((HLOCAL) pNewACL);

      return(FALSE);

   }

   // STEP 15: Set our new DACL to the file SD

   if (!SetSecurityDescriptorDacl(psdNewSD,

                     TRUE,

                     pNewACL,

                     FALSE))

   {

      printf("Error %d:SetSecurityDescriptorDacl",GetLastError());

      LocalFree((HLOCAL) pNewACL);

      return(FALSE);

   }

   // STEP 16: Set the SD to the File

   if (!SetFileSecurity(pFileName, DACL_SECURITY_INFORMATION,psdNewSD))

   {

      printf("Error %d:SetFileSecurity\n",GetLastError());

      LocalFree((HLOCAL) pNewACL);

      return(FALSE);

   }

   // STEP 17: Free the memory allocated for the new ACL

   LocalFree((HLOCAL) pNewACL);

   return(TRUE);

}

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Computing the Size of a New ACL

Article ID: Q102103

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

When adding an access-allowed access control entry (ACE) to a discretionary

access control list (DACL), it is useful to know the exact size needed for

the new DACL. This is particularly useful when creating a new DACL and

copying over the existing ACEs. The below code computes the size needed for

a DACL if an access-allowed ACE is added:

   ACL_SIZE_INFORMATION AclInfo;

   GetAclInformation(pACL,&AclInfo,sizeof(ACL_SIZE_INFORMATION),

                     AclSizeInformation))

   dwNewACLSize = AclInfo.AclBytesInUse +

                  sizeof(ACCESS_ALLOWED_ACE) +

                  GetLengthSid(UserSID) - sizeof(DWORD);

MORE INFORMATION

================

The call to GetAclInformation() takes a pointer to an ACL. This point is

supplied by your program and should point to the DACL you want to add an

access-allowed ACE to. The GetAclInformation() call fills out a

ACL_SIZE_INFORMATION structure, which provides size information on the ACL.

The second statement computes what the new size of the ACL will be if an

access-allowed ACE is added. This is accomplished by adding the current

bytes being used to the size of an ACCESS_ALLOWED_ACE. We then add the size

of the security identifier (SID) (provided by your application) that is to

used in the AddAccessAllowedAce() API call. Subtracting out the size of a

DWORD is the final adjustment needed to obtain the exact size. This adjust

is to compensate for a place holder member in the ACCESS_ALLOWED_ACE

structure which is used in variable length ACEs.

When adding an ACE to an existing ACL, often there is not enough free space

in the ACL to accommodate the additional ACE. In this situation, it is

necessary to allocate a new ACL and copy over the existing ACEs and then

add the access-allowed ACE. The above code can be used to determine the

amount of memory to allocate for the new ACL.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: FILE_READ_EA and FILE_WRITE_EA Specific Types

Article ID: Q102104

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The FILE_READ_EA and FILE_WRITE_EA specific types provide access to read

and write a file's extended attributes. Specific access types are

represented as bits in the access mask and are specific to the object type

associated with the mask.

Please note that these specific types are used in the definition of

constants such as FILE_GENERIC_READ, and are not intended to be generally

used when specifying access (generic access types are much more

appropriate).

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: System GENERIC_MAPPING Structures

Article ID: Q102105

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

There is not a Win32 application programming interface (API) to retrieve

the GENERIC_MAPPING structures for Windows NT objects. The MapGenericMask()

Win32 API is intended to use GENERIC_MAPPING structures associated with

private objects created by the application.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Why LoadLibraryEx() Returns an HINSTANCE

Article ID: Q102128

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

In the Win32 Help files, LoadLibrary() is typed to return a HANDLE, while

LoadLibraryEx() is prototyped to return a HINSTANCE.

An HINSTANCE return from LoadLibraryEx() is useful because processes that

load dynamic-link libraries (DLLs) do not necessarily want the overhead of

having to page in code for a DllEntryPoint routine when the DLL does not

need to initialize information. This is especially useful when you have

multiple threads that attach to already loaded DLLs. In this case, you may

want to not implicitly load via LoadLibrary() and instead use

LoadLibraryEx() to explicitly load without having to page in the code for

every attach.

LoadLibraryEx() is also useful if you want to retrieve resources from a DLL

or an EXE. In this case, you would use LoadLibraryEx() to load the module

you want into your address space, without executing DLLEntryPoint, and then

use the resource application programming interfaces (APIs) to access the

data.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseDll


INF: Passing a Pointer to a Member Function to the Win32 API

Article ID: Q102352

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Many of the Win32 application programming interfaces (APIs) call for a

callback routine. One example is the lpStartAddr argument of

CreateThread():

   HANDLE CreateThread(lpsa, cbStack, lpStartAddr, lpvThreadParm,

      fdwCreate, lpIDThread)

   LPSECURITY_ATTRIBUTES lpsa;    /* Address of thread security attrs */

   DWORD cbStack;                    /* Initial thread stack size*/

   LPTHREAD_START_ROUTINE lpStartAddr; /* Address of thread function */

   LPVOID lpvThreadParm;       /* Argument for new thread*/

   DWORD fdwCreate;               /* Creation flags*/

   LPDWORD lpIDThread;               /* Address of returned thread ID */

When attempting to use a member function as the thread function, the

following error is generated:

   error C2643: illegal cast from pointer to member

The problem is that the function expects a C-style callback, not a pointer

to a member function. A major difference is that member functions are

called with a hidden argument called the "this" pointer. In addition, the

format of the pointer isn't simply the address of the first machine

instruction, as a C pointer is. This is particularly true for virtual

functions.

If you want to use a member function as a callback, you can use a static

member function. Static member functions do not receive the "this" pointer

and their addresses correspond to an instruction to execute.

Static member functions can only access static data, and therefore to

access nonstatic class members, the function needs an object or a pointer

to an object. One solution is to pass in the "this" pointer as an argument

to the member function.

MORE INFORMATION

================

This situation occurs with callback functions of other types as well, such

as:

   DLGPROC                  GRAYSTRINGPROC

   EDITWORDBREAKPROC        LINEDDAPROC

   ENHMFENUMPROC            MFENUMPROC

   ENUMRESLANGPROC          PROPENUMPROC

   ENUMRESNAMEPROC          PROPENUMPROCEX

   ENUMRESTYPEPROC          TIMERPROC

   FONTENUMPROC             WNDENUMPROC

   GOBJENUMPROC

For more information on C++ callbacks, please see the May issue of the

"Windows Tech Journal."

The following sample demonstrates how to use a static member function as a

thread function, and pass in the "this" pointer as an argument.

Sample Code

-----------

#include <windows.h>

class A

{

public:

   int x;

   int y;

   A() { x = 0; y = 0; }

   static StartRoutine( A * );   // Compiles clean, includes "this" pointer

};

void main( )

{

   A a;

   DWORD dwThreadID;

   CreateThread( NULL,

      0,

      (LPTHREAD_START_ROUTINE)(a.StartRoutine),

      &a,                        // Pass "this" pointer to static member fn

      0,

      &dwThreadID

   );

}

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Detecting Closure of Command Window from a Console App

Article ID: Q102429

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Win32 console applications run in a command window. For the console

application to detect when the console is closing, register a console

control handler and look for the following values in your case statement:

   CTRL_CLOSE_EVENT     User closes the console

   CTRL_LOGOFF_EVENT    User logs off

   CTRL_SHUTDOWN_EVENT  User shuts down the system

For an example, see the CONSOLE sample. For more information, see the entry

for SetConsoleCtrlhandler() in the Win32 application programming interface

(API) reference.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCon


INF: Definition of a Protected Server

Article ID: Q102447

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The Win32 application programming interface (API) reference briefly

discusses creating a "protected server" that assigns security to private

objects. This article explains the concept of a protected server" and its

relationship to private objects.

MORE INFORMATION

================

A protected server is an application that provides services to clients.

These services could be as simple as saving and retrieving information from

a database while issuing security checks to verify that the client has

proper access.

A private object is an application-defined data structure that both the

client and server recognize. Private objects are not registered with nor

recognized by the Windows NT operating system; they are entirely

application-defined.

It is not uncommon for security to be assigned to private objects in a

protected server's database. For example, when a client asks the server to

create a new object in the database, the server could use the

CreatePrivateObjectSecurity() Win32 API to create a security descriptor

(SD) for the new private object. The server would then store the SD with

the private object in the database. It is important to note that there is

nothing in the SD that associates it with the private object. Instead, it

is up to the protected server to maintain that association in the private

object or in the database. It is likely that the private object and the

associated SD would be stored together in a single database record.

A protected server application is responsible for checking a client's

access before providing information. For example, when a client asks the

server to retrieve some data, the server would go out and locate the record

(which would contain the private object and SD) and bring a copy of the SD

into memory. It would then call the AccessCheck() Win32 API passing the SD,

the clients access token, and the desired access mask. AccessCheck() will

check the client's access against the object's SD to determine if access is

permitted. Depending on the result of AccessCheck(), the protected server

would either provide the requested information or deny access.

In conclusion, a protected server is a application that performs operations

on private objects that are entirely user defined. The protected server is

responsible for associating security descriptors to those objects and must

take the steps necessary to verify a client's access.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: How Windows NT Handles Floating-Point Calculations

Article ID: Q102555

--------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

--------------------------------------------------------------

SUMMARY

=======

Each thread in a Win32 application has its own general register set

(provided by the kernel) and its own floating-point state. However, the

floating-point support available in a specific instance depends on the

subsystem or component in question.

Below is a list of various components and environments and what type of

floating-point support is present for them.

MORE INFORMATION

================

Win32

-----

Floating-point support is available to any thread running in the Win32 or

POSIX subsystem.

This is true even on x86 machines that do not have floating-point hardware.

The floating-point instructions are emulated automatically for the thread.

This feature allows people writing code in higher level languages, such as

C, to assume floating-point support. The compiler generates the appropriate

floating-point machine code. In addition, some standard floating-point

functions allow applications to use floating-point exceptions in a portable

manner. [For more information, see the header file FPIEE.H and the filter

function fpieee_flt().]

POSIX

-----

Again, POSIX applications can be created with the assumption of available

floating-point support.

Note that the POSIX standard does not define a way to enable floating-point

exceptions, so POSIX applications that do so must rely on some system-

specific features. Under Windows NT, a POSIX application can enable

floating exceptions by using _controlfp(). Floating-point exceptions can

then be caught by SIGFPE, or, if the application needs to do more than

simply catch the exception, by fpieee_flt().

MS-DOS/WOW: x86

---------------

MS-DOS and WOW applications are run directly by the processor in virtual-86

mode. An MS-DOS/WOW application has access to the floating-point hardware

just as it would appear in MS-DOS. (If no floating-point hardware is

present, no emulation is provided for the application.)

MS-DOS/WOW: Non-x86

-------------------

When run on a RISC-based computer, or other non-x86 machine using the

Windows/NT 80286 emulation code, the 80287 floating-point instructions are

directly emulated. The MS-DOS/WOW application behaves as if an 80287

processor were present.

OS/2 (Supported Only on x86 Versions of Windows NT)

---------------------------------------------------

Floating-point support in this subsystem matches that of OS/2: if there's

no floating-point hardware installed, the OS/2 application is expected to

provide its own emulation.

Device Drivers: x86

-------------------

On x86 platforms, a driver cannot use the coprocessor. Moreover, using any

floating-point instruction (including fnsave or fwait) in the driver could

cause either corruption of the user's numeric state or a bug check.

Device Drivers: MIPS/Alpha

--------------------------

For non-ISR time (that is, execution that does not occur during the

interrupt service routine [ISR]), floating-point support can be assumed. At

ISR time, floating-point support is available so long as the driver

registered the ISR with IoConnectInterrupt and passed FloatingSave as TRUE.

This causes the system to save and restore the volatile floating-point

registers around the associated ISR.

Note that these functions on RISC-based computers use floating-point:

RtlFillMemory(), RtlZeroMemory(), RtlCopyMemory(), RtlMoveMemory(). If an

ISR calls any of these functions, it must connect to the interrupt with

FloatingSave=TRUE on a MIPS.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Security Attributes on Named Pipes

Article ID: Q102798

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The March beta release of the Windows NT (and earlier) did not require

security attributes on pipes. It was valid at that time to enter NULL for

the last parameter of the Win32 application programming interface (API)

CreateNamedPipe(). This is no longer the case.

MORE INFORMATION

================

Windows NT 3.1 and later require security attributes for pipes. Please note

that setting the security attributes parameter to NULL does not indicate

that you want a NULL security descriptor (SD), rather it indicates that you

want to inherit the security descriptor of the current access token. This

generally means that any client wanting to connect to your pipe server must

have the same security attributes as the user that started the server. For

example, if the user who started the server was the administrator of the

machine, then any client who wants to connect must also be an administrator

to that machine.

Below is an code sample that demonstrates creating a named pipe with a NULL

security descriptor.

   HANDLE               hPipe;    // Pipe handle.

   SECURITY_ATTRIBUTES  sa;       // Security attributes.

   PSECURITY_DESCRIPTOR pSD;      // Pointer to SD.

   // Allocate memory for the security descriptor.

   pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,

                                SECURITY_DESCRIPTOR_MIN_LENGTH);

   // Initialize the new security descriptor.

   InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);

   // Add a NULL descriptor ACL to the security descriptor.

   SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE);

   sa.nLength = sizeof(sa);

   sa.lpSecurityDescriptor = pSD;

   sa.bInheritHandle = TRUE;

   // Create a local named pipe with a NULL security descriptor.

   hPipe = CreateNamedPipe(

         "\\\\.\\PIPE\\test",    // Pipe name = 'test'.

         PIPE_ACCESS_DUPLEX      // 2-way pipe.

         | FILE_FLAG_OVERLAPPED, // Use overlapped structure.

         PIPE_WAIT               // Wait on messages.

         | PIPE_READMODE_MESSAGE // Specify message mode pipe.

         | PIPE_TYPE_MESSAGE,

         MAX_PIPE_INSTANCES,     // Maximum instance limit.

         OUT_BUF_SIZE,           // Buffer sizes.

         IN_BUF_SIZE,

         TIME_OUT,               // Specify time out.

         &sa);                   // Security attributes.

It is important to note that by specifying TRUE for the fDaclPresent

parameter and NULL for pAcl parameter of the SetSecurityDescriptorDacl()

API, a NULL access control list (ACL) is being explicitly specified.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseIpc


INF: Using Temporary File Can Improve Application Performance

Article ID: Q103237

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The use of temporary files can significantly increase the performance of an

application.

MORE INFORMATION

================

By using CreateFile() with the FILE_ATTRIBUTE_TEMPORARY flag, you let the

system know that the file is likely to be short lived. The temporary file

is created as a normal file. The system needs to do a minimal amount of

lazy writes to the file system to keep the disk structures (directories and

so forth) consistent. This gives the appearance that the file has been

written to the disk. However, unless the Memory Manager detects an

inadequate supply of free pages and starts writing modified pages to the

disk, the Cache Manager's Lazy Writer may never write the data pages of

this file to the disk. If the system has enough memory, the pages may

remain in memory for any arbitrary amount of time. Because temporary files

are generally short lived, there is a good chance the system will never

write the pages to the disk.

To further increase performance, your application might mark the file as

FILE_FLAG_DELETE_ON_CLOSE. This indicates to the system that when the last

handle of the file is closed, it will be deleted. Although the system

generally purges the cache to ensure that a file being closed is updated

appropriately, because a file marked with this flag won't exist after the

close, the system foregoes the cache purge.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: Copy on Write Page Protection for Windows NT

Article ID: Q103858

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The Windows NT's Copy on Write page protection is a concept that allows

multiple applications to map their virtual address spaces to share the same

physical pages, until an application needs to modify the page and have its

own instance copy. This is part of a technique called Lazy Evaluation,

which allows the system to not waste time by committing resources, time, or

execution until/unless absolutely necessary. Copy on Write allows the

virtual memory manager to save memory and execution time.

MORE INFORMATION

================

Copy on Write works as follows: In generic terms, an application can load

something into its virtual memory (for example, a code section or DLL

code). Virtual memory is mapped to physical memory. Another process may

want to load the same thing into its virtual memory. As long as neither

process writes to this memory, they can map to, and share, the same

physical pages.

If either process needs to write to this memory, because the memory is

marked as Copy on Write, the physical page frame will be copied somewhere

else in physical memory. Fixups are made for the virtual memory mapping of

the writing process. Both applications now have their own instance of the

memory contents. In short, applications can share the same physical memory

with Copy on Write, until one of the applications has to modify the

contents. At that point, a new copy of the contents is made, and the

writing process has its own copy.

It should be emphasized that this is not to say that applications are

sharing memory in the sense that one application can write to it and

another can read what the first one wrote; as long as applications are only

going to read a piece of memory (for example, a code section), then the

physical pages supporting that memory for the applications can be shared.

Once the application needs to write to the memory (for example, in the form

of a fixup), then that application must have a new physical page so that

the modifications are not seen by other processes. The processes are no

longer sharing the same physical pages.

Applications

------------

When multiple instances of the same Windows application load, you may

notice that most, if not all, of their instance handles (hInstance) have

the same value. In fact, almost all of the windows on the desktop have this

value, which represents the base address where the application loaded in

virtual memory.

Each of the instances of the same application running has its own protected

virtual address space to run in. If each of these applications can load

into its default base address, each will map to, and be able to share, the

same physical pages in memory. Using Copy on Write, the system will allow

these applications to share the same physical pages until one of the

applications modifies a page. Then a copy is made in physical memory, and

that process's virtual memory is fixed up to use the new physical page. If

for some reason one of these instances cannot load in the desired base

address, it will get its own physical pages. See the section on DLLs below

for more explanation.

DLLs

----

Dynamic-link libraries (DLLs) are created with a default base address to

load at. Assuming that multiple applications call the DLL, they will all

try to load it within their own address space at that default virtual

address. If they are all successful, they can all map that virtual address

space to share the same physical pages.

However, if for some reason the DLL cannot be loaded within the process's

address space at the default address, it will load the DLL elsewhere. The

DLL must be copied into another physical address frame. The reason is that

fixups for jump instructions in a DLL are written as specific locations

within the DLL's pages. If the DLL can be loaded at the same base address

for each process, the second to the nth process does not have to write that

memory location for the jump. If a process cannot load the DLL at the

specified base address, the locations written in the DLL's jumps will be

different for this process. This forces the fixup to write a new location

into the jump, and the Copy on Write will automatically force a new

physical page.

Note that all references to data must be fixed up too. If this causes

virtual memory of the code section to be updated, then the process will

again go through the Copy on Write process. For instance, if there are a

great many places in the code section that make reference into data in a

DLL, if the DLL cannot be loaded at its default location, the locations in

the code section data in the DLL are referenced will have to be modified.

If this is one of multiple instances of a process, these fixups must go

through the copy on write process, and the virtual memory pages of the

process's code section will not be able to map and share the same physical

pages as the other instances. If there are a lot of references to the data

in the DLL by the code section, this can essentially cause the entire code

section to be copied to new physical pages.

POSIX

-----

In POSIX, there is a fork() instruction that basically creates two copies

of the same program. It is an expensive process for the system to copy the

address space of one process into another. Instead, under Windows NT, the

system simply marks the parent's pages with Copy on Write. This way new

physical frames are copied only if and when they are needed (have been

modified). The system does not waste time or memory if all of the address

space doesn't need to be copied. (For more information, see "Inside Windows

NT" by Microsoft Press).

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMm


INF: Detecting Logoff from a Service

Article ID: Q104122

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

Sometimes it is handy for a service to know whether or not a user is logged

on to the system. For instance, suppose that there are circumstances under

which the service displays a dialog box and waits for the user to respond.

If this is done while the user is logged off, the service is blocked until

the user logs on again.

Unfortunately, there is no direct way for a service to detect whether or

not a user is logged on. There is, however, an indirect method. If you

supply MB_DEFAULT_DESKTOP_ONLY as one of the flags in the fuStyle parameter

of MessageBox(), the function will fail if no one is logged on.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseService


INF: Mapping .INI File Entries to the Registry

Article ID: Q104136

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

Under Windows NT, .INI file variables are mapped into the Registry as

defined in the

   HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\IniFile

mapping key. The Win32 Profile application programming interface (API)

functions look for a mapping by looking up the filename extension portion

of the profile file. If a match is found, then the search continues under

that node for the specified application name. If a match is found, then the

search continues for the variable name. If the variable name is not found,

the value of the (NULL) variable name is a string that points to a node in

the Registry, whose value keys are the variable names. If a specific

mapping is found for the variable name, then its value points to the

Registry value that contains the variable value.

The Profile API calls go to the Windows server to look for an actual .INI

file, and read and write its contents, only if no mapping for either the

application name or filename is found. If there is a mapping for the

filename but not the application name, and there is a (NULL) application

name, the value of the (NULL) variable will be used as the location in the

Registry of the variable, after appending the application name to it.

In the string that points to a Registry node, there are several

prefixes that change the behavior of the .INI file mapping:

   ! - This character forces all writes to go both to the Registry and

       to the .INI file on disk.

   # - This character causes the Registry value to be set to the value

       in the Windows 3.1 .INI file when a new user logs in for the

       first time after setup.

   @ - This character prevents any reads from going to the .INI file

       on disk if the requested data is not found in the Registry.

   USR: - This prefix stands for HKEY_CURRENT_USER, and the text after

          the prefix is relative to that key.

   SYS: - This prefix stands for HKEY_LOCAL_MACHINE\Software, and the

          text after the prefix is relative to that key.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Creating a Font for Use with the Console

Article ID: Q105299

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

It is possible to use FontEdit to create a font that can be used by the

console. The following must be true:

 - The face name must be System, Terminal, or Courier

 - The font size must be different from any of the other console fonts

 - The font must be fixed pitch

 - The font must not be italic

In addition, in the U.S. market, the font should support codepage 437.

Install the font from the Control Panel. After rebooting, the font will be

available to the console.

An EnumFonts() call is made by the console during its initialization to

determine what fonts are available. The console saves a set of one-to-one

mappings between the font sizes listed and a set of LOGFONTs. The console

never has direct knowledge of what file is used.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCon


INF: Monitoring a Log File for an Event

Article ID: Q105301

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The following undocumented function is being exposed in order to provide a

temporary workaround for customers requiring this functionality. Microsoft

will provide an officially supported Win32 API which provides this

functionality in the next release.

As there are no guarantees that ElfChangeNotify() will be supported in all

future releases, we recommend that you rewrite your code to use the

supported Win32 API at the time that it becomes available.

MORE INFORMATION

================

To receive notification when something is written to the log file, use

the following undocumented application programming interface (API):

   UINT ElfChangeNotify( LogHandle, Event )

   HANDLE LogHandle,

   HANDLE Event

This function will cause the Event to be signaled when an event has

been written to the log file identified by the LogHandle.

   LogHandle

      Handle to a log file obtained from a call to OpenEventLog().

   Event

      A handle to a Win32 event.

Note that you must link with ADVAPI32.LIB.

Most of the ELF (Event Logging Facility) functions already have Win32

wrappers. ElfChangeNotify() does not have such a wrapper at this time,

but will have a wrapper in the next release. At that time, it is

recommended that code that uses ElfChangeNotify() be rewritten to use

the new Win32 API, because ElfChangeNotify() may not be supported as

is in the future.

Additional reference words: 3.10 logfile

KBCategory: Prg

KBSubcategory: BseMisc


INF: Cancelling WaitCommEvent() with SetCommMask()

Article ID: Q105302

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

If a serial port is in nonoverlapped mode (without FILE_FLAG_OVERLAPPED)

and SetCommMask() is called, the call does not return until any pending

WaitCommEvent() calls return. This apparently contradicts the following

statement from the SetCommMask() Help

   If SetCommMask() is called for a communications resource while a wait

   is pending for that resource, WaitCommEvent() returns an error.

and the following statement from the WaitCommEvent() Help:

   If a process attempts to change the device handle's event mask by

   using the SetCommMask() function while a WaitCommEvent() operation

   is in progress, WaitCommEvent() returns immediately.

However, this is the expected behavior. If you open a serial port in the

nonoverlapped mode, then you can do only one thing at a time with the

serial port. SetCommMask() must block while the WaitCommEvent() call is

blocking.

If the serial port was opened with FILE_FLAG_OVERLAPPED, WaitCommEvent()

will return after SetCommEvent() has been called.

Additional reference words: 3.10 com1 com2

KBCategory: Prg

KBSubcategory: BseCommapi


BUG: Redirecting Output to an MS-DOS Application

Article ID: Q105303

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The following method is used to redirect output to a child process when it

is started from a GUI application:

1. Declare STARTUPINFO si.

   a. Set the hStdIn, hStdOut, and/or hStdErr field as desired.

   b. Set the dwFlags field to STARTF_USESTDHANDLES.

2. In CreateProcess(), set inherit handles to TRUE.

NOTE: This method does not work when starting MS-DOS applications.

RESOLUTION

==========

As a workaround, use AllocConsole(), then the following method:

1. Use SetStdHandle() to set the desired handles to be inherited.

   -or-

   Use DuplicateHandle() to change the inheritance property of handles

   that should not be inherited.

3. In CreateProcess(), set inherit handles to TRUE.

This method creates a blank console window; however, this is necessary

because the method doesn't work otherwise.

STATUS

======

Microsoft has confirmed this problem to be a bug in Windows NT 3.1.

MORE INFORMATION

================

Note that if you are opening a handle that will be inherited by the

child, set SECURITY_ATTRIBUTES.bInheritHandle = TRUE in the call to

CreateFile(), CreatePipe(), and so forth.

For an example of both methods of redirection, see the INHERIT SDK

sample.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseProcThrd


INF: SetErrorMode() Is Inherited

Article ID: Q105304

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

An application can use SetErrorMode() to control whether Windows NT handles

serious errors or whether the application itself will handle the errors.

NOTE: The error mode will be inherited by any child process. However, the

child process may not be prepared to handle the error return codes. As a

result, the application may die during a critical error without the usual

error message popups occurring.

This behavior is by design.

One solution is to call SetErrorMode() before and after the call to

CreateProcess() in order to control the error mode that is passed to the

child. Be aware that this process must be synchronized in a multithreaded

application.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseExcept


INF: Calling CRT Output Routines from a GUI Application

Article ID: Q105305

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

To use C Run-time output routines, such as printf(), from a GUI

application, it is necessary to create a console. The Win32 application

programming interface (API) AllocConsole() creates the console. The CRT

routine setvbuf() removes buffering so that output is visible immediately.

This method works if the GUI application is run from the command line or

from File Manager. However, this method does not work if the application is

started from the Program Manager or via the "start" command. The following

code shows how to work around this problem:

   int hCrt;

   HFILE *hf;

   AllocConsole();

   hCrt = _open_osfhandle(

             (long) GetStdHandle(STD_OUTPUT_HANDLE),

             _O_TEXT

          );

   hf = _fdopen( hCrt, "w" );

   *stdout = *hf;

   i = setvbuf( stdout, NULL, _IONBF, 0 );

This code opens up a new low-level CRT handle to the correct console output

handle, associates a new stream with that low-level handle, and replaces

stdout with that new stream. This process takes care of functions that use

stdout, such as printf(), puts(), and so forth. Use the same procedure for

stdin and stderr.

Note that this code does not correct problems with handles 0, 1, and 2. In

fact, due to other complications, it is not possible to correct this, and

therefore it is necessary to use stream I/O instead of low-level I/O.

MORE INFORMATION

================

When a GUI application is started with the "start" command, the three

standard OS handles STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, and

STD_ERROR_HANDLE are all "zeroed out" by the console initialization

routines. These three handles are replaced by valid values when the GUI

application calls AllocConsole(). Therefore, once this is done, calling

GetStdHandle() will always return valid handle values. The problem is that

the CRT has already completed initialization before your application gets a

chance to call AllocConsole(); the three low I/O handles 0, 1, and 2 have

already been set up to use the original zeroed out OS handles, so all CRT

I/O is sent to invalid OS handles and CRT output does not appear in the

console. Use the workaround described above to eliminate this problem.

In the case of starting the GUI application from the command line without

the "start" command, the standard OS handles are NOT correctly zeroed out,

but are incorrectly inherited from CMD.EXE. When the application's CRT

initializes, the three low I/O handles 0, 1, and 2 are initialized to use

the three handle numbers that the application inherits from CMD.EXE. When

the application calls AllocConsole(), the console initialization routines

attempt to replace what the console initialization believes to be invalid

standard OS handle values with valid handle values from the new console. By

coincidence, because the console initialization routines tend to give out

the same three values for the standard OS handles, the console

initilization will replace the standard OS handle values with the same

values that were there before--the ones inherited from CMD.EXE. Therefore,

CRT I/O works in this case.

It is important to realize that the ability to use CRT routines from a GUI

application run from the command line was not by design so this may not

work in future versions of Windows NT. In a future version, you may need

the workaround not just for applications started on the command line with

"start <application name>", but also for applications started on the

command line with "application name".

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Getting and Using a Handle to a Directory

Article ID: Q105306

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

CreateDirectory() can be used to open a new directory. An existing

directory can be opened by calling CreateFile(). To open an existing

directory with CreateFile(), it is necessary to specify the flag

FILE_FLAG_BACKUP_SEMANTICS. The following code shows how this can be done:

   HANDLE hFile;

   hFile = CreateFile( "c:\\mstools",

              GENERIC_READ | GENERIC_WRITE,

              FILE_SHARE_WRITE,

              NULL,

              OPEN_EXISTING,

              FILE_FLAG_BACKUP_SEMANTICS,

              NULL

           );

   if( hFile == INVALID_HANDLE_VALUE )

      MessageBox( NULL, "CreateFile() failed", NULL, MB_OK );

The handle obtained can be used to obtain information about the directory

or to set information about the directory. For example:

   BY_HANDLE_FILE_INFORMATION fiBuf;

   FILETIME ftBuf;

   SYSTEMTIME stBuf;

   char msg[40];

   GetFileInformationByHandle( hFile, &fiBuf );

   FileTimeToLocalFileTime( &fiBuf.ftLastWriteTime, &ftBuf );

   FileTimeToSystemTime( &ftBuf, &stBuf );

   wsprintf( msg, "Last write time is %d:%d  %d/%d/%d",

      stBuf.wHour,stBuf.wMinute,stBuf.wMonth,stBuf.wDay,stBuf.wYear );

   MessageBox( NULL, msg, NULL, MB_OK );

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: Named Pipe Buffer Size

Article ID: Q105531

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The documentation for CreateNamedPipe() indicates that

   The input and output buffer sizes are advisory. The actual buffer

   size reserved for each end of the named pipe is either the system

   default, the system minimum or maximum, or the specified size

   rounded up to the next allocation boundary.

The buffer size specified should be a reasonable size so that your process

will not run out of nonpaged pool, but it should also be large enough to

accommodate typical requests.

Every time a named pipe is created, the system creates the inbound and/or

outbound buffers using nonpaged pool, which is the physical memory used by

the kernel. The number of pipe instances (as well as objects such as

threads and processes) that you can create is limited by the available

nonpaged pool. Each read or write request requires space in the buffer for

the read or write data, plus additional space for the internal data

structures.

Whenever a pipe write operation occurs, the system first tries to charge

the memory against the pipe write quota. If the remaining pipe write quota

is enough to fulfill the request, the write completes immediately.

If the remaining pipe write quota is too small to fulfill the request, the

system will try to expand the buffers to accommodate the data using

nonpaged pool reserved for the process. The write will block until the data

is read from the pipe so that the additional buffer quota can be released.

Therefore, if your specified buffer size is too small, the system will grow

the buffer as needed, but the downside is that the operation will block. If

the operation is overlapped, a system thread is blocked; otherwise, the

application thread is blocked.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseIpc


INF: The Use of PAGE_WRITECOPY

Article ID: Q105532

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The documentation to CreateFileMapping(), VirtualAlloc(), and

VirtualProtect() indicates that the PAGE_WRITECOPY protection gives

copy-on-write access to the committed region of pages. As it is,

PAGE_WRITECOPY makes sense only in the context of file mapping, where

you want to map something from the disk into your view and then modify

the view without causing the data to go on the disk.

The only case where VirtualAlloc() should succeed with PAGE_WRITECOPY

is the case where CreateFileMapping() is called with -1 and allocates

memory with the SEC_RESERVE flag and later on, VirtualAlloc() is used

to change this into MEM_COMMIT with a PAGE_WRITECOPY protection.

There is a bug in Windows NT 3.1 such that the following call to

VirtualAlloc() will succeed:

   lpCommit = VirtualAlloc(lpvAddr, cbSize, MEM_COMMIT, PAGE_WRITECOPY);

NOTE: lpvAddr is a pointer to memory that was allocated with

MEM_RESERVE and PAGE_NOACCESS.

One case where this might be useful is when emulating the UNIX fork

command. Emulating fork behavior would involve creating instance data

and using threads or multiple processes.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMm


BUG: Problems with Local/Global Memory Management APIs

Article ID: Q105533

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The following is a list of problems that may be encountered when the Local

and Global memory management application programming interfaces (APIs) are

used:

1. The documentation for LocalUnlock() says that if the specified

   memory is fixed, the API returns nonzero.

   The API returns 0 (zero) even if the memory is fixed.

2. The documentation for LocalReAlloc() states that if the cbBytes

   parameter is 0, the memory is movable and discardable, and the lock

   count is zero, then the API returns a handle to a discarded memory

   object. If the lock count is nonzero, the API will fail.

   The API succeeds even if the lock count is nonzero.

3. The documentation for LocalFree() and for GlobalFree() indicates

   that if the parameter is NULL, the function will fail and the

   system generate an access violation.

   The APIs do not generate an access violation.

4. The documentation for LocalFree() and for GlobalFree() states that

   the API will fail if passed a handle to a memory object that is

   locked.

   The APIs free the memory even if the lock count is nonzero.

RESOLUTION/STATUS

=================

The following are confirmations of the corresponding problems

described in the previous section:

1. This is an error in the documentation. Memory that is already

   unlocked will cause LocalUnlock() to return FALSE and

   GetLastError() will report ERROR_NOT_LOCKED. Memory allocated with

   LMEM_FIXED always has a lock count of zero, and therefore

   GetLastError() will also return ERROR_NOT_LOCKED in this case.

2. This is a bug in Local/GlobalReAlloc().

3. This is an error in the documentation. The Help should state that

   Local/GlobalFree() will return NULL if an attempt is made to free

   NULL. This is compatible with Windows 3.1.

4. This is a bug in Local/GlobalFree().

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMm


BUG: AllocConsole() Does Not Set Error Code on Failure

Article ID: Q105564

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The documentation for AllocConsole() states the following:

   If the function succeeds, the return value is TRUE; otherwise, it

   is FALSE. To get extended error information, use the GetLastError()

   function.

Upon failure, AllocConsole() does not set the error code.

STATUS

======

Microsoft has confirmed this to be a bug in Windows NT 3.1.

MORE INFORMATION

================

The following sample code demonstrates the problem:

#include <stdio.h>

#include <windows.h>

void main()

{

   BOOL bSuccess;

/* Comment out the following line and GetLastError() will   */

/* return 999; otherwise, GetLastError() returns 1812.      */

   FreeConsole();

   SetLastError( 999 );

   bSuccess = AllocConsole();

   if( !bSuccess )

      puts( "AllocConsole failed" );

   printf( "The last error is: %d\n", GetLastError() );

   getchar();

}

Additional reference words: 3.10

KBCategory:

KBSubcategory: BseCon


INF: Setting the Console Configuration

Article ID: Q105674

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

To create a command prompt with custom features such as

   Settings

   Fonts

   Screen Size and Position

   Screen Colors

create a new entry in the Program Manager for CMD.EXE (suppose that the

description is CUSTOM), choose these items from the CMD system menu, and

select Save Configuration in each dialog box. The settings are saved in the

registry under

   HKEY_CURRENT_USER\

             Console\

             custom

and are used when starting the CUSTOM command prompt from the Program

Manager or when specifying:

   start "custom"

This behavior is really a convenient side effect of

   start <string>

which sets the title in the window title bar. When you create a new console

window with the START command, the system looks in the registry and tries

to match the title with one of the configurations stored there. If it

cannot find it, it defaults to the values stored in:

   HKEY_CURRENT_USER\

             Console\

       Configuration

This functionality can be duplicated in your own applications using the

registry application programming interface (API).

For more information, please see the "Registry and Initialization Files"

overview and the REGISTRY sample.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: First and Second Chance Exception Handling

Article ID: Q105675

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Structured exception handling (SEH) takes a little getting used to,

particularly when debugging. It is common practice to use SEH as a

signaling mechanism. Some application programming interfaces (APIs)

register an exception handler in anticipation of a failure condition that

is expected to occur in a lower layer. When the exception occurs, the

handler may correct or ignore the condition rather than allowing a failure

to propagate up through intervening layers. This is very handy in complex

environments such as networks where partial failures are expected and it is

not desirable to fail an entire operation simply because one of several

optional parts failed. In this case, the exception can be handled so that

the application is not aware that an exception has occurred.

However, if the application is being debugged, it is important to realize

that the debugger will see all exceptions before the program does. This is

the distinction between the first and second chance exception. The debugger

gets the "first chance," hence the name. If the debugger continues the

exception unhandled, the program will see the exception as usual. If the

program does not handle the exception, the debugger will see it again (the

"second chance"). In this latter case, the program normally would have

crashed had the debugger not been present.

If you do not want to see the first chance exception in the debugger, then

disable the feature. Otherwise, during execution, when the debugger gets

the first chance, continue the exception unhandled and allow the program to

handle the exception as usual. Check the documentation for the debugger

that you are using for descriptions of the commands to be used.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseExcept


INF: Critical Sections Versus Mutexes

Article ID: Q105678

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Critical sections and mutexes provide synchronization that is very similar,

except that critical sections can be used only by the threads of a single

process. There are two areas to consider when choosing which method to use

within a single process:

1. Speed. The Synchronization overview says the following about

   critical sections:

      ... critical section objects provide a slightly faster, more

      efficient mechanism for mutual-exclusion synchronization.

   Critical sections use a processor-specific test and set instruction

   to determine mutual exclusion.

2. Deadlock. The Synchronization overview says the following about

   mutexes:

      If a thread terminates without releasing its ownership of a

      mutex object, the mutex is considered to be abandoned. A waiting

      thread can acquire ownership of an abandoned mutex, but the wait

      function's return value indicates that the mutex is abandoned.

   WaitForSingleObject() will return WAIT_ABANDONED for a mutex that

   has been abandoned. However, the resource that the mutex is

   protecting is left in an unknown state.

   There is no way to tell whether a critical section has been

   abandoned.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSync


PRB: GetPrivateProfileSection() Can Read Only 32K Sections

Article ID: Q105681

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The documentation for GetProfileSection(), GetProfileString(),

GetPrivateProfileSection(), GetPrivateProfileString(), and

GetPrivateProfileSection() indicate that the application programming

interface (API) can read all the keys and values of a section, regardless

of size. However, these functions only seem to handle sections that are

smaller than 32K, even though the size of the buffer is a DWORD.

CAUSE

=====

The code is casting this value to a signed short, and therefore you are

having problems with sections that are greater than 32K in size.

STATUS

======

Microsoft has confirmed this to be a problem in Windows NT 3.1. We are

researching this problem and will post new information here in this

Knowledge Base as it becomes available.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Using NTFS Alternate Data Streams

Article ID: Q105763

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The documentation for the NTFS file system states that NTFS supports

multiple streams of data; however, the documentation does not address

the syntax for the streams themselves.

The Windows NT Resource Kit documents the stream syntax as follows:

   filename:stream

Alternate data streams are strictly a feature of the NTFS file system

and may not be supported in future file systems. However, NTFS will be

supported in future versions of Windows NT.

Future file systems will support a model based on Object Linking and

Embedding (OLE) version 2.0 structured storage (IStream and IStorage).

By using OLE 2.0, an application can support multiple streams on any

file system and all supported operating systems (Windows, Macintosh,

Windows NT, and Win32s), not just Windows NT.

MORE INFORMATION

================

The following sample code demonstrates NTFS streams:

#include <windows.h>

#include <stdio.h>

void main( )

{

   HANDLE hFile, hStream;

   DWORD dwRet;

   hFile = CreateFile( "testfile",

                    GENERIC_WRITE,

                 FILE_SHARE_WRITE,

                             NULL,

                      OPEN_ALWAYS,

                                0,

                             NULL );

   if( hFile == INVALID_HANDLE_VALUE )

      printf( "Cannot open testfile\n" );

   else

      WriteFile( hFile, "This is testfile", 16, &dwRet, NULL );

   hStream = CreateFile( "testfile:stream",

                             GENERIC_WRITE,

                          FILE_SHARE_WRITE,

                                      NULL,

                               OPEN_ALWAYS,

                                         0,

                                      NULL );

   if( hStream == INVALID_HANDLE_VALUE )

      printf( "Cannot open testfile:stream\n" );

   else

      WriteFile( hStream, "This is testfile:stream", 23, &dwRet, NULL );

}

The file size obtained in a directory listing is 16, because you are

looking only at "testfile", and therefore

   type testfile

produces the following:

   This is testfile

However

   type testfile:stream

produces the following:

   The filename syntax is incorrect

In order to view what is in testfile:stream, use:

   more < testfile:stream

   -or-

   mep testfile:stream

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: RegSaveKey() Requires SeBackupPrivilege

Article ID: Q106383

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The description for RegSaveKey() states the following:

   The caller of this function must possess the SeBackupPrivilege

   security privilege.

This means that the application must explicitly open a security token and

enable the SeBackupPrivilege. By granting a particular user the right to

back up files, you give that user the right only to gain access to the

security token (that is, the token is not automatically created for the

user but the right to create such a token is given). You must add

additional code to open the token and enable the privilege.

MORE INFORMATION

================

The following code demonstrates how this can be done:

   static HANDLE           hToken;

   static TOKEN_PRIVILEGES tp;

   static LUID             luid;

   // Enable backup privilege.

   OpenProcessToken( GetCurrentProcess(),

      TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ;

   LookupPrivilegeValue( NULL, "SeBackupPrivilege", &luid );

   tp.PrivilegeCount           = 1;

   tp.Privileges[0].Luid       = luid;

   tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

   AdjustTokenPrivileges( hToken, FALSE, &tp,

      sizeof(TOKEN_PRIVILEGES), NULL, NULL );

   // Insert your code here to save the registry keys/subkeys.

   // Disable backup privilege.

   AdjustTokenPrivileges( hToken, TRUE, &tp, sizeof(TOKEN_PRIVILEGES),

      NULL, NULL );

Note that you cannot create a process token; you must open the existing

process token and adjust its privileges.

The DDEML Clock sample has similar code sample at the end of the CLOCK.C

file where it obtains the SeSystemTimePrivilege so that it can set the

system time.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Sharing Objects with a Service

Article ID: Q106387

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

To share objects (file mapping, synchronization, and so forth) created

by a service, you must place a null DACL (discretionary access-control

list) in the security descriptor field when the object is created.

This grants everyone access to the object.

MORE INFORMATION

================

This null DACL is not the same as a NULL, which is used to specify the

default security descriptor. For example, the following code can be used to

create a mutex with a null DACL:

   PSECURITY_DESCRIPTOR    pSD;

   SECURITY_ATTRIBUTES     sa;

   pSD = (PSECURITY_DESCRIPTOR) LocalAlloc( LPTR,

                  SECURITY_DESCRIPTOR_MIN_LENGTH);

   if (pSD == NULL)

   {

      Error(...);

   }

   if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))

   {

      Error(...);

   }

   // Add a NULL DACL to the security descriptor..

   if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE))

   {

      Error(...);

   }

   sa.nLength = sizeof(sa);

   sa.lpSecurityDescriptor = pSD;

   sa.bInheritHandle = TRUE;

   mutex = CreateMutex( &sa, FALSE, "SOMENAME" );

If you are creating one of these objects in an application and the object

will be shared with a service, you could also use a null DACL to grant

everyone access. As an alternative, you could add an access-control entry

(ACE) to the DACL that grants access to the user account that the service

is running under. This would restrict access to the object to the service.

For a more detailed example, please see the SERVICES sample.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Accessing the Macintosh Resource Fork

Article ID: Q106663

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Resource forks are implemented as NTFS streams named AFP_Resource. There is

no structure to the fork; it is exactly whatever the Macintosh writes to

it. The resource fork can be written to using standard Win32 application

programming interfaces (APIs). Refer to the forks as

<FileName>:AFP_Resource.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


FIX: VirtualLock() on File-Mapped Pages Hangs Computer

Article ID: Q107642

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

Your computer may stop responding (hang) if you use the VirtualLock()

application programming interface (API) command to lock a file-mapped

page.

STATUS

======

Microsoft has confirmed this to be a problem in Windows NT and

Windows NT Advanced Server version 3.1. This problem was corrected in

the latest U.S. Service Pack for Windows NT and Windows NT Advanced

Server version 3.1. For information on obtaining the Service Pack,

query on the following word in the Microsoft Knowledge Base (without

the spaces):

   S E R V P A C K

Additional reference words: 3.10

KBCategory: Prg

KBSubCategory: BseMm


INF: Retrieving Counter Data From the Registry

Article ID: Q107728

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The performance data begins with a structure of type PERF_DATA_BLOCK and is

followed by PERF_DATA_BLOCK.NumObjectTypes data blocks. Each data block

begins with a structure of type PERF_OBJECT_TYPE, followed by

PERF_OBJECT_TYPE.NumCounters structures of type PERF_COUNTER_DEFINITION.

Next, there are PERF_OBJECT_TYPE.NumInstances structures of type

PERF_INSTANCE DEFINITION, each directly followed by an instance name, a

structure of type PERF_COUNTER_BLOCK and PERF_OBJECT_TYPE.NumCounters

counters. All of these data types are described in WINPERF.H.

MORE INFORMATION

================

The following steps are used to retrieve all of the counter information

from the registry:

1. Allocate a buffer to obtain the performance data. Call

   RegQueryValueEx() to obtain the data. If the call returns

   ERROR_MORE_DATA, then the buffer size was not big enough. Increase the

   size of the buffer and try again. Repeat until the call is successful.

      PPERF_DATA_BLOCK PerfData = NULL;

      PerfData = (PPERF_DATA_BLOCK) malloc( BufferSize );

      while( RegQueryValueEx( HKEY_PERFORMANCE_DATA,

                                    "Global",

                                        NULL,

                                        NULL,

                                    PerfData,

                                     &dwSize ) == ERROR_MORE_DATA )

      {

         free( PerfData );

         IncreaseBufferSize( );

         PerfData = (PPERF_DATA_BLOCK) malloc( BufferSize );

      }

2. Get the first object:

      PPERF_OBJECT_TYPE PerfObj;

      PerfObj = (PPERF_OBJECT_TYPE) ((PBYTE)PerfData +

                                      PerfData->HeaderLength);

3. Get the first instance:

      PPERF_INSTANCE_DEFINITION PerfInst;

      PerfInst = (PPERF_INSTANCE_DEFINITION) ((PBYTE)PerfObj +

                                               PerfObj->DefinitionLength);

4. Get the first counter:

      PPERF_COUNTER_DEFINITION PerfCntr;

      PerfCntr = (PPERF_COUNTER_DEFINITION) ((PBYTE)PerfObj +

                                                 PerfObj->HeaderLength);

5. Get the counter data:

      PPERF_COUNTER_BLOCK PtrToCntr;

      PVOID CntrData;

      if( PerfInst != NULL )

         PtrToCntr = (PPERF_COUNTER_BLOCK) ((PBYTE)PerfInst +

                                             PerfInst.ByteLength );

      else PtrToCntr = (PPERF_COUNTER_BLOCK) ((PBYTE)PerfObj +

                                             PerfObj.DefinitionLength );

      PVOID CntrData = (PVOID)((PBYTE)PtrToCntr + PerfCntr.CounterOffset);

6. Get the next counter, repeat steps 5 and 6 until all NumCounters

   counters are retrieved:

      PerfCntr = (PPERF_COUNTER_DEFINITION) ((PBYTE)PerfCntr +

                                              PerfCntr->ByteLength);

7. After all the counters are retrieved for the instance, get the next

   instance, repeat steps 4-6 until all NumInstances instances are

   retrieved:

      PPERF_COUNTER_BLOCK PtrToCntr;

      PPERF_INSTANCE_DEFINITION PerfInst;

      PtrToCntr = (PPERF_COUNTER_BLOCK) ((PBYTE) PerfInst +

                                          PerfInst->ByteLength);

      PerfInst = (PPERF_INSTANCE_DEFINITION) ((PBYTE) PtrToCntr +

                                          PtrToCntr->ByteLength);

8. After all instances of the object type are retrieved, move to the next

   object type, repeat steps 3-7 until all NumObjectTypes object types are

   handled:

      PerfObj = (PPERF_OBJECT_TYPE)((PBYTES)PerfObj +

                                     PerfObj.TotalByteLength);

Note that the instance names are retrieved in a fashion that is similar to

retrieving the data.

The steps above showed how to obtain all of the counters. You can retrieve

only the counters that pertain to a particular object by using the titles

database. The information is stored in the registry in the format index,

name, index, name, and so forth.

To retrieve the titles database and store it in TitlesDatabase:

1. Open the key:

      RegOpenKeyEx( HKEY_LOCAL_MACHINE,

         "Software\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009",

                0,

         KEY_READ,

            &Hkey);

   Note that 009 is a language ID, so this value will be different on a

   non-English version of the operating system.

2. Query the information from the key:

      RegQueryInfoKey(

                   Hkey,

         (LPTSTR) Class,

             &ClassSize,

                   NULL,

                &Subkey,

              MaxSubKey,

              &MaxClass,

                &Values,

               &MaxName,

               &MaxData,

               &SecDesc,

          &LastWriteTime );

3. Allocate a buffer to store the information:

      TitlesDataBase = (PSTR) malloc( (MaxData+1) * sizeof(TCHAR) )

4. Retrieve the data:

      RegQueryValueEx(     Hkey,

            (LPTSTR) "Counters",

                           NULL,

                           NULL,

        (LPBYTE) TitlesDataBase,

                       &MaxData );

Once you have the database, it is possible to write code that will go

through all objects, searching by index (field ObjectNameTitleIndex) or by

type (field ObjectNameTitle - which is initially NULL).

Or, you could obtain only the performance data for specified objects by

changing the call to ReqQueryValueEx() in step 1 of the SUMMARY section

above to:

   RegQueryValueEx( HKEY_PERFORMANCE_DATA,

                           Indices,

                              NULL,

                              NULL,

                          PerfData,

                           &dwSize );

Note that the only difference here is that instead of specifying "Global"

as the second parameter, you specify a string that represents the decimal

value(s) for the object(s) of interest that are obtained from the titles

database.

The PVIEWER and PERFMON samples in the MSTOOLS\SAMPLES\SDKTOOLS directory

contain complete sample code that deals with performance data. The

"Performance Overview" and Volume 3 of the Windows NT Resource Kit also

contain information about performance monitoring.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Replace IsTask() with GetExitCodeProcess()

Article ID: Q108228

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

In Windows 3.1, the application programming interface (API) IsTask() can be

used to determine whether a process is still running or whether it has

terminated. As the Win32 API help file indicates, this function is obsolete

in Windows NT.

To get this functionality through the Win32 API, use the API

GetExitCodeProcess(). This function takes the handle as the first parameter

and returns the exit code or STILL_ACTIVE in the second parameter:

   BOOL GetExitCodeProcess(hProcess, lpdwExitCode)

   HANDLE hProcess;

   LPDWORD lpdwExitCode;

As an alternative, you can also use WaitForSingleObject(). Pass the process

handle as the first parameter and a timeout value for the second parameter:

   DWORD WaitForSingleObject(hObject, dwTimeout)

   HANDLE hObject;

   DWORD dwTimeout;

The process handle is signaled when the process terminates. Pass in 0

(zero) for the timeout if you would like to poll or start another thread to

wait with an INFINITE timeout value.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseProcThrd


INF: Accessing the Event Logs

Article ID: Q108230

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Event logs are used to store significant events, such as warnings, errors,

or information. There are five operations that can be performed on event

logs through the event logging application programming interface (API):

backup, clear, query, read, and write.

The default event logs are the Application event log, the Security event

log, and the System event log. Access to these event logs is determined by

which account the application is running under.

MORE INFORMATION

================

The following table shows which accounts are granted access to which logs

and what type of access is granted:

   Log           Account     Access Granted

   -------------------------------------------

   Application   LocalSys    read write clear

                 Admins      read write clear

                 ServerOp    read write clear

                 World       read write

   Security      LocalSys    read write clear

                 Admins      read       clear

   System        LocalSys    read write clear

                 Admins      read       clear

                 ServerOp    read       clear

                 World       read

   -------------------------------------------

   Table 1 - access granted

The Local System account (LocalSys) is a special account that may be used

by Windows NT services. The Administrator account (Admins) consists of the

administrators for the system. The Server Operator account (ServerOp)

consists of the administrators of the domain server. The World account

includes all users on all systems.

The following table shows which types of access are required for the

corresponding event logging API:

   Event Logging API         Access Required

   -------------------------------------------

   OpenEventLog()            read

   OpenBackupEventLog()      read

   RegisterEventSource()     write

   ClearEventLog()           clear

   -------------------------------------------

   Table 2 - access required

As an example, OpenEventLog() requires read access (see Table 2). A member

of the ServerOp account can call OpenEventLog() for the Application event

log and the System event log, because ServerOp has read access for both of

these logs (see Table 1). However, a member of the ServerOp account cannot

call OpenEventLog() for the Security log, because it does not have read

access for this log (see Table 1).

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: CreateFileMapping() SEC_* Flags

Article ID: Q108231

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The definition of CreateFileMapping() is as follows:

   HANDLE CreateFileMapping(hFile, lpsa, fdwProtect, dwMaximumSizeHigh,

      dwMaximumSizeLow, lpszMapName)

   HANDLE hFile;

   LPSECURITY_ATTRIBUTES lpsa;

   DWORD fdwProtect;

   DWORD dwMaximumSizeHigh;

   DWORD dwMaximumSizeLow;

   LPCTSTR lpszMapName;

The following flags are four possible values for the parameter fdwProtect:

   SEC_COMMIT

      All pages of a section are to be set to the commit state.

   SEC_IMAGE

      The file specified for a section's file mapping is an executable

      image file.

   SEC_NOCACHE

      All pages of a section are to be set as noncacheable.

   SEC_RESERVE

      All pages of a section are to be set to the reserved state.

If none of these flags are specified, SEC_COMMIT is the default. This

behaves the same way as MEM_COMMIT in VirtualAlloc().

MORE INFORMATION

================

The SEC_RESERVE flag is intended for file mappings that are backed by the

paging file, and therefore use SEC_RESERVE only when hFile is -1. The pages

are reserved just as they are when the MEM_RESERVE flag is used in

VirtualAlloc(). The pages can be committed by subsequently using the

VirtualAlloc() application programming interface (API), specifying

MEM_COMMIT. Once committed, these pages cannot be decommitted.

The SEC_NOCACHE flag is intended for architectures that require various

locking structures to be located in memory that is not ever fetched into

the CPU cache. On x86 and MIPS machines, use of this flag just slows down

the performance because the hardware keeps the cache coherent. Certain

device drivers may require noncached data so that programs can write

through to the physical memory. SEC_NOCACHE requires that either

SEC_RESERVE or SEC_COMMIT be used in addition to SEC_NOCACHE.

The SEC_IMAGE flag indicates that the file handle points to an executable

file, and it should be loaded as such. The mapping information and file

protection are taken from the image file, and therefore no other options

are allowed when SEC_IMAGE is used.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMm


DOCERR: WM_COPYDATA Is Also Supported on Win32s

Article ID: Q108402

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

There are a number of methods that two processes (both 32-bit, or one 32-

bit and one 16-bit) can use to communicate on both Windows NT and Win32s.

These methods include the use of dynamic data exchange (DDE), the

clipboard, and object linking and embedding (OLE), all of which can involve

some amount of overhead.

Windows NT introduces a new message, WM_COPYDATA, which can be used to pass

data from one application to another. The Win32 "Programmer's Reference"

contains the following description

   WM_COPYDATA

   wParam = (WPARAM) (HWND) hwndFrom;

   lParam = (LPARAM) (PCOPYDATASTRUCT) pcds;

where wParam is the handle of the sending window and pcds is a pointer to

the structure that contains the data.

The documentation does not indicate that this message is supported under

Win32s; however, WM_COPYDATA is supported under Win32s.

Note that under Win32s, WM_COPYDATA does not actually copy the data--it

only translates the pointers to the data. If the receiving application

changes the buffer, then the data is changed for both applications.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Use LoadLibrary() on .EXE Files Only for Resources

Article ID: Q108448

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The LoadLibrary() application programming interface (API) can be used to

load an executable module. A common use of this function is to load a

dynamic-link library (DLL), perform a subsequent call to GetProcAddress()

to get the address of an exported DLL routine, and call this DLL routine

through the address that is returned. Another use of LoadLibrary() is to

load an executable module and retrieve its resources.

In Windows NT, a LoadLibrary() of an .EXE file is supported only for the

purposes of retrieving resources. It was decided that it was rather

uncommon to load an .EXE for any other purpose, so this limitation was

imposed on LoadLibrary() to improve the performance in loading resources.

Calling a routine in an .EXE through an address obtained with

GetProcAddress() can cause an access violation.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Working Set Size, Nonpaged Pool, and VirtualLock()

Article ID: Q108449

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

This article discusses memory management issues such as working set size,

nonpaged pool, and locking pages into physical memory via VirtualLock().

MORE INFORMATION

================

Working Set

-----------

A process's working set is the set of pages that it has currently in

memory. The values for maximum working set and minimum working set are hard-

coded in Windows NT and are thus impossible to change. There are three

values hard-coded for the maximum working set. The value used for maximum

working set depends on whether your machine is considered to be a small,

medium, or large machine:

   Small machine--less than 16 megabytes (MB)

   Medium machine--between 16 MB and 20 MB

   Large machine--greater than 20 MB

The system tries to keep about 4 MB free to reduce the paging that occurs

when loading a new process, allocating memory, and so forth. Any free RAM

beyond what the system requires is available for the system to use to

increase your working set size if your process is doing a lot of paging.

Process pages that are paged out of your process space are moved into the

"standby list," where they remain until sufficient free RAM is available,

or until system memory is low and they need to be reused. If these pages

are accessed by your process while they are still on the standby list and

more RAM has become available, they will be "soft-faulted" back into the

working set. This does not require any disk access, so it is very quick.

Therefore, even though you have an upper limit to the size of your working

set, you can still have quite a few process pages in memory that can be

pulled back into your working set very quickly.

To minimize working set requirements and increase performance, use the

Working Set Tuner, WST.EXE, to order the functions within your code. One

way to help an application receive a larger working set is to use the

Network application in the Control Panel to set the server configuration to

"Maximize Throughput for Network Applications."

Nonpaged Pool

-------------

System memory is divided into paged pool and nonpaged pool. Paged pool can

be paged to disk, whereas nonpaged pool is never paged to disk. Important

system data is stored in nonpaged pool. For example, each Windows NT object

created requires a block of nonpaged pool. In fact, it is the availability

of nonpaged pool that determines how many processes, threads, and other

such objects can be created. The error that you will receive if you have

too many object handles open is:

   1816 (ERROR_NOT_ENOUGH_QUOTA)

The default amount of nonpaged pool also depends on whether your machine is

considered small, medium, or large. In other words, you will have X amount

of nonpaged pool on a 16 MB machine, Y amount of nonpaged pool on a 20 MB

machine, and Z amount of nonpaged pool on a machine with more than 20 MB.

(The exact numbers for X, Y, and Z have not been made public and they may

change in future versions.)

The Windows NT "Resource Kit, Volume I" documents that it is possible to

change the amount of nonpaged pool by modifying the following registry

entry:

   HKEY_LOCAL_MACHINE\SYSTEM\

      CurrentControlSet\

      Control\

      Session Manager\

      Memory Management\

      NonPagedPoolSize

WARNING: This modification can cause the system to crash, and therefore

Microsoft does not recommend that this registry entry be changed.

VirtualLock()

-------------

To lock a particular page into memory so that it cannot be swapped out to

disk, use VirtualLock(). The documentation for VirtualLock() states the

following:

   Locking pages into memory may degrade the performance of the system by

   reducing the available RAM and forcing the system to swap out other

   critical pages to the paging file. There is a limit on the number of

   pages that can be locked: 30 pages. The limit is intentionally small to

   avoid severe performance degradation.

There is no way to raise this limit--it is fixed at 30 pages in Windows NT

version 3.1. The reason that you see a severe performance degradation when

an application locks these pages is that Windows NT must reload all locked

pages whenever there is a context switch to this application. Windows NT

was designed to minimize page swapping, so it is often best to let the

system handle swapping itself, unless you are writing a device driver that

needs immediate access to memory.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMm


INF: Sharing All Data in a DLL

Article ID: Q109619

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Win32 dynamic-link libraries (DLLs) use instance data by default in Windows

NT. This means that each application that uses a DLL gets its own copy of

the DLLs data. However, it is possible to share the DLL data among all

applications that use the DLL.

If you only need to share some of the DLL data, we recommend creating a

new section and sharing it instead. For additional information, please see

the following article(s) in the Microsoft Knowledge Base:

   ARTICLE-ID: Q89817

   TITLE     : INF: How to Specify Shared and Nonshared Data in a DLL

If you want to share *all* of the DLL static data, it is important to

do two things:

 - First, the DLL must use the DLL version of the C Run-time (for example

   CRTDLL.DLL or MSVCRT10.DLL). Please see your product documentation for

   more information about using the C Run-time in a DLL.

 - Second, you will need to specify that both .data and .bss are shared.

   Often, this is done in the "SECTIONS" portion of the .DEF file. For

   example:

      SECTIONS

         .bss  READ WRITE SHARED

         .data READ WRITE SHARED

   If you are using Visual C++ for Windows NT, you will have to specify

   this using the -section switch on the linker. For example:

      link -section:.data,rws -section:.bss,rws

Only static data will be shared. Memory allocated dynamically with calls to

APIs/functions such as GlobalAlloc() or malloc() will still be specific to

the calling process.

The system will try to load the shared memory block at the same address in

each process. However, if the block cannot be loaded into the same memory

address, the system allocates a new block of memory for that process and

the memory is not shared. No run time warnings are given when this happens,

therefore, named shared memory is generally a safer option.

MORE INFORMATION

================

The C Run-time uses global variables. If the CRT is statically linked to

the DLL, these variables will be shared among all clients of the DLL and

will most likely cause an exception c0000005.

The reason you need to specify both .data and .bss as shared is because

they each hold different types of data. The .data section holds initialized

data and the .bss section holds the uninitialized data.

One reason for sharing all data in a DLL is to have consistent behavior in

the DLL between Win32 (running on Windows NT) and Win32s (running on

Windows 3.1). When running on Win32s, a 32-bit DLL shares its data among

all of the processes that use the DLL.

Note that it is not necessary to share all data to behave identically

between Win32 and Win32s. The DLL can use thread local storage (TLS) on

Win32s to store variables as instance data. For additional information,

please see the following article(s) in the Microsoft Knowledge Base:

   ARTICLE-ID: Q109620

   TITLE     : INF: Creating Instance Data in a Win32s DLL

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseDll


PRB: ERROR_INVALID_PARAMETER from WriteFile() or ReadFile()

Article ID: Q110148

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The WriteFile() or ReadFile() function call may fail with the error

ERROR_INVALID_PARAMETER if you are operating on a named pipe and using

overlapped I/O.

CAUSE

=====

A possible cause for the failure is that the Offset and OffsetHigh members

of the OVERLAPPED structure are not set to zero.

RESOLUTION

==========

Set the Offset and OffsetHigh members of your OVERLAPPED structure to zero.

STATUS

======

This behavior is by design. The online help for both WriteFile() and

ReadFile() state that the Offset and OffsetHigh members of the OVERLAPPED

structure must be set to zero or the functions will fail.

MORE INFORMATION

================

In many cases the function calls may succeed if you do not explicitly set

OVERLAPPED.Offset and OVERLAPPED.OffsetHigh to zero. However, this is

usually either because the OVERLAPPED structure is static or global and

therefore is initialized to zero, or the OVERLAPPED structure is automatic

(local) and the contents of that location on the stack are already zero.

You should explicitly set the OVERLAPPED.Offset and OVERLAPPED.OffsetHigh

structure members to zero.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


PRB: Can't Increase Process Priority

Article ID: Q110853

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

--------

An attempt to increase process priority to the real-time priority

REALTIME_PRIORITY_CLASS may not set the PriorityClass to the expected

level.

CAUSE

-----

Only accounts with the "Increase Scheduling Priority" permission can

increase the priority to real-time. Only Administrators and "Power Users"

have this permission by default.

RESOLUTION

----------

Either run the program from an Administrator or Power User account, or

grant the Increase Scheduling Priority permission to any user group that

must run the program.

STATUS

------

This behavior is by design.

MORE INFORMATION

================

The Increase Scheduling Priority permission can be granted to a user or

group through the User Manager. To do this:

1. Open the Administrative Tools group in Program Manager.

2. Run the User Manager application.

3. Choose User Rights from the Policies menu.

4. Select the Show Advanced User Rights check box.

5. Select Increase Scheduling Priority from the drop-down list box.

6. Choose the Add button to add users or groups to the list of entities

   that have this right.

Note that the call to SetPriorityClass() may return success even though the

priority was not set to REALTIME_PRIORITY_CLASS, because if you dont have

the Increase Scheduling Priority permission, a request for

REALTIME_PRIORITY_CLASS is interpreted as a request for the highest

priority class allowed in the current account. If it is important to know

the actual priority class that was set, use the GetPriorityClass()

function.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseProcThrd


INF: New Owner in Take-Ownership Operation

Article ID: Q111541

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

When ownership of a file is taken, the user performing the operation

becomes the new owner. The exception to this rule is when the user is a

member of the "Administrators" group. In this situation, the ownership of

the file is assigned to the Administrators group.

The reasoning for this behavior is that the administrators on a particular

system work together. When one administrator takes ownership of a file, the

others should also receive access.

MORE INFORMATION

================

When a take-ownership operation is performed, the system assigns the new

owner SID based on the TOKEN_OWNER field of the users access token.

When a user logs on to a Windows NT system, the logon process builds an

access token to represent the user. Normally the TOKEN_OWNER field in the

access token is set equal to TOKEN_USER (the users SID). However, when the

user is a member of the Administrators group, the system sets the

TOKEN_OWNER field to the Administrators SID.

Although Windows NT does not provide a user interface for changing the

TOKEN_OWNER field in the users access token, it is possible to

programatically change this value via the SetTokenInformation() Win32 API

(application programming interface).

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Checking for Administrators Group

Article ID: Q111542

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

It is often useful to know if the account under which your application is

running is a member of the "Administrators" group. The sample code below

demonstrates a method of making this determination:

Sample Code

-----------

BOOL IsAdmin(void)

{

   HANDLE hProcess, hAccessToken;

   UCHAR InfoBuffer[1024];

   PTOKEN_GROUPS ptgGroups = (PTOKEN_GROUPS)InfoBuffer;

   DWORD dwInfoBufferSize;

   SID_NAME_USE snuInfo;

   UCHAR szAccountName[256], szDomainName[256];

   DWORD dwAccountNameSize, dwDomainNameSize;

   UINT x;

   hProcess = GetCurrentProcess();

   if(!OpenProcessToken(hProcess,TOKEN_READ,&hAccessToken))

      return(FALSE);

   if(!GetTokenInformation(hAccessToken,TokenGroups,InfoBuffer,

     1024, &dwInfoBufferSize)) return(FALSE);

   for(x=0;x<ptgGroups->GroupCount;x++)

   {

      dwAccountNameSize = 256;

      dwDomainNameSize = 256;

      LookupAccountSid(NULL, ptgGroups->Groups[x].Sid,

      szAccountName, &dwAccountNameSize,

      szDomainName, &dwDomainNameSize, &snuInfo);

      if(!strcmp(szAccountName,"Administrators") &&

      !strcmp(szDomainName,"BUILTIN"))

      return(TRUE);

  }

  return(FALSE);

}

MORE INFORMATION

================

The sample code above begins by obtaining a handle to the access token via

the OpenProcessToken() API (application programming interface). The

GetTokenInformation() API is then called to obtain the TOKEN_GROUPS

structure for the access token. The sample then looks up the name of each

group via the LookupAccountSid() API and compares it to Administrators. If

a group with an account name Administrators and domain name "BUILTIN" is

found, then the sample returns TRUE indicating the user is a member of the

Administrators group.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Creating a World SID

Article ID: Q111543

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The sample code below demonstrates how to create a World Security

Identifier (SID). The World SID (S-1-1-0) is a group that includes all

users. To determine if a SID (perhaps in an Access Control Entry) is the

World SID, you must first create a World SID to compare it to. Once you

have created a World SID, you can use the EqualSid() API (application

programming interface) to determine equality.

Sample Code

-----------

PSID psidWorldSid;

SID_IDENTIFIER_AUTHORITY siaWorldSidAuthority =

     SECURITY_WORLD_SID_AUTHORITY;

psidWorldSid = (PSID)LocalAlloc(LPTR,GetSidLengthRequired( 1 ));

InitializeSid( psidWorldSid, &siaWorldSidAuthority, 1);

*(GetSidSubAuthority( psidWorldSid, 0)) = SECURITY_WORLD_RID;

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Looking Up the Current User and Domain

Article ID: Q111544

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Program Manager displays the logged in user account and domain name in its

windows title. This information can be retrieved programmatically by

extracting the user SID from the current access token and then looking up

the account and domain name via the LookupAccountSid() Win32 API. Below is

sample code demonstrating this technique:

Sample Code

-----------

void ShowUserDomain(void)

{

     HANDLE hProcess, hAccessToken;

       UCHAR InfoBuffer[1000],szAccountName[200], szDomainName[200];

       PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer;

       DWORD dwInfoBufferSize,dwAccountSize = 200, dwDomainSize = 200;

       SID_NAME_USE snu;

       hProcess = GetCurrentProcess();

       OpenProcessToken(hProcess,TOKEN_READ,&hAccessToken);

       GetTokenInformation(hAccessToken,TokenUser,InfoBuffer,

            1000, &dwInfoBufferSize);

       LookupAccountSid(NULL, pTokenUser->User.Sid, szAccountName,

            &dwAccountSize,szDomainName, &dwDomainSize, &snu);

    printf("%s\\%s\n",szDomainName,szAccountName);

}

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Security Context of Child Processes

Article ID: Q111545

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

When a process is created with the CreateProcess() API, it operates under

the same security context as the parent. The child process inherits the

parents security context, which are defined by the parents access token.

Even if a thread in the parent process impersonates a client and then

creates a new process, the new process still runs under the parents

original security context and not the under the impersonation token.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Taking Ownership of Registry Keys

Article ID: Q111546

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

To take ownership of a registry key it is necessary to have a handle to the

key. A handle to the key can be obtained by opening the key with a registry

API (application programming interface) such as RegOpenKeyEx(). If the user

does not have access to the registry key, the open operation will fail and

this will in turn prevent ownership being taken (because a handle to the

key is required to change the keys security).

The solution to this problem is to first enable the TakeOwnership privilege

and then to open the registry key with WRITE_OWNER access as shown below:

   RegOpenKeyEx(HKEY_CLASSES_ROOT,"Testkey",0,WRITE_OWNER,&hKey);

This function call will provide a handle to the registry, which can be used

in the following call to take ownership:

   RegSetKeySecurity(hKey,OWNER_SECURITY_INFORMATION, &SecurityDescriptor);

Please note that you will need to initialize the security descriptor being

passed to RegSetKeySecurity() and set the owner field to the new owner SID.

Taking ownership of a registry key is not a common operation. It is

typically an operation that an administrator would use as a last resort to

gain access to a registry key.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


PRB: GetExitCodeProcess Always Returns 0 for 16-Bit Processes

Article ID: Q111559

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

SYMPTOMS

--------

GetExitCodeProcess() always returns a status of 0 (zero) when the handle

for a 16-bit process is passed. This applies to both Windows NT and Win32s.

STATUS

------

Microsoft has confirmed this to be a limitation in Windows NT version 3.1

and Win32s version 1.1. Microsoft may add functionality in future versions

that support exit codes from 16-bit processes.

Additional reference words: 3.10 1.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: ERROR_BUS_RESET May Be Benign

Article ID: Q111837

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Tape API (application programming interface) functions may return an error

code of ERROR_BUS_RESET when operating on SCSI tape devices. In many cases,

you can ignore this error value and retry the operation. However, this

error is fatal if received during a series of write operations because a

tape drive cannot recover from a bus reset and continue writing.

MORE INFORMATION

================

When Windows NT boots up it resets the SCSI bus. This bus reset is reported

by the tape drive in response to the first operation after the reset.

The code fragment shown below in the Sample Code section could be used to

check for ERROR_BUS_RESET and clear it. The same technique could be used

for other informational errors, such as ERROR_MEDIA_CHANGED, that may not

be relevant at application startup.

Sample Code

-----------

/*

** This is a code fragment only and will not compile and run as is.

*/

   ...

   do {

      dwError = GetTapeStatus(hTape);

   } while (dwError == ERROR_BUS_RESET);

   ...

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: Possible Cause for ERROR_INVALID_FUNCTION

Article ID: Q111838

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The Win32 Tape API (application programming interface) functions may return

an error code of ERROR_INVALID_FUNCTION if the operation being attempted is

not supported by the tape device.

MORE INFORMATION

================

You can determine what operations are valid for a tape device by calling

GetTapeParameters() to get the tape drive parameters. See the code fragment

in the Sample Code section of this article for an example of how to call

GetTapeParameters() for this information.

Once you have the TAPE_GET_DRIVE_PARAMETERS structure, you can check for a

specific operation in the FeaturesLow and FeaturesHigh members of the

TAPE_GET_DRIVE_PARAMETERS structure. This is also demonstrated in the

Sample Code section.

Sample Code

-----------

/*

** This is a code fragment only and will not compile and run as is.

*/

DWORD dwRes, dwSize;

TAPE_GET_DRIVE_PARAMETERS parmDrive;

...

dwSize = sizeof(parmDrive);

dwRes = GetTapeParameters(hTape, GET_TAPE_DRIVE_INFORMATION,

                &dwSize, &parmDrive);

if (dwRes != NO_ERROR) {

    /* place error handling code here */

    exit(-1);

}

if (parmDrive.FeaturesLow & TAPE_DRIVE_ERASE_LONG)

    printf("Device supports the long erase technique.\n");

...

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


DOCERR: EofChar Field of DCB Structure Is Not Supported

Article ID: Q115083

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The documentation for the device control block (DCB) structure says that

the EofChar field specifies the value of the character used to signal

the end of the data over the communications resource. However, this

setting seems to have no effect.

RESOLUTION

==========

DCB.EofChar is not currently supported in Windows NT.

MORE INFORMATION

================

When DCB.EofChar is supported, you should call ClearCommError() after

every read to see whether COMSTAT.fEof is set. When COMSTAT.fEof is set,

this means that DCB.EofChar has been received.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: BseCommapi


INF: Retrieving Time-Zone Information

Article ID: Q115231

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.5

----------------------------------------------------------------------

For Windows NT, version 3.1, the time-zone strings were compiled into a

resource that is linked into the CONTROL.EXE file. For Windows NT,

version 3.5, the time-zone strings have been moved into the registry.

The time-zone strings are located in

   HKEY_LOCAL_MACHINE\SOFTWARE\

      Microsoft\

      Windows NT\

      CurrentVersion\

      Time Zones.

For each time zone, the registry key TZI is formatted as follows:

   LONG       Bias;

   LONG       StandardBias;

   LONG       DaylightBias;

   SYSTEMTIME StandardDate;

   SYSTEMTIME DaylightDate;

You can use this information to fill out a TIME_ZONE_INFORMATION structure,

which is used when calling SetTimeZoneInformation().

Additional reference words: 3.50

KBCategory: Prg

KBSubcategory: BseMisc


INF: Timer Resolution in Windows NT

Article ID: Q115232

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.5

----------------------------------------------------------------------

The GetTickCount() timer resolution on Windows NT, version 3.1, is

15 milliseconds (ms) for x86 and 10 ms for MIPS and Alpha. On Windows NT,

version 3.5, the GetTickCount() timer resolution is 10 ms on the 486 or

greater, but the resolution is still 15 ms on a 386.

NOTE: The measurements in milliseconds indicate the period of the

interrupt, not the units of the returned value.

The Win32 API QueryPerformanceCounter() returns the resolution of a high-

resolution performance counter if the hardware supports one. For x86, the

resolution is about 0.8 microseconds (0.0008 ms). For MIPS, the resolution

is about twice the clock speed of the processor. You need to call

QueryPerformanceFrequency() to get the frequency of the high-resolution

performance counter.

NOTE: These numbers are likely to change in future versions.

Additional reference words: 3.50

KBCategory: Prg

KBSubcategory: BseMisc


DOCERR: References to APIs that Do Not Exist

Article ID: Q115233

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The "Win32 Programmer's Reference," volume 2, section 54.4.3, "Changing

User Profiles" (page 233), lists the following sequence of APIs that need

to be called in order to change a user profile:

   WriteProfileString

   RevertToSelf

However, ImpersonateClient(), OpenProfileUserMapping(), and

CloseProfilerUserMapping() are not documented Win32 APIs.

RESOLUTION

==========

In a server application, if you want to change another user's context, you

must impersonate the user, using ImpersonateNamedPipeClient(),

ImpersonateDdeClientWindow(), DdeImpersonateClient(), or

RpcImpersonateClient() as appropriate.

At one point in time, Open/CloseProfileUserMapping() were present in the

Win32 API, but they were later removed. The printed documents do not

reflect this change.

The correct sequence of APIs is as follows:

   hPipe = CreateNamedPipe( ... );

   RegCloseKey( HKEY_CURRENT_USER );

   ImpersonateNamedPipeClient( hPipe, ... );

   RegOpenKey( HKEY_CURRENT_USER, ... );

   // Make your modifications to client's HKEY_CURRENT_USER.

   RegCloseKey( HKEY_CURRENT_USER );

   RevertToSelf( );

   RegOpenKey( HKEY_CURRENT_USER, ... );

   CloseHandle( hPipe );

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: BseMisc


INF: Long Filenames on Windows NT FAT Partitions

Article ID: Q115236

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.5

----------------------------------------------------------------------

SUMMARY

=======

Windows NT, version 3.5, introduces the ability to create or open files

with long filenames (LFN) on Windows NT file allocation table (FAT)

partitions.

UNICODE is stored on disk, so that the original name is always preserved

for extended characters regardless of which code page happens to be active

when reading from or writing to the disk.

The legal character set is that of the Windows NT file system (NTFS)

(except for the ":" for opening NTFS alternative file streams), so you can

copy arbitrary files between NTFS and FAT without losing any of the

filename information.

MORE INFORMATION

================

The LFNs are not available from the MS-DOS DIR command, but they are

available from the Windows NT DIR command. When you create an LFN on a

Windows NT FAT partition, an accompanying short name is created just as

on an NTFS partition. You can access the file or directory with either

the long names or the short names under Windows NT.

For instance, use the Microsoft Editor (MEP) to create a file named as

follows on a FAT partition under Windows NT:

   longfilename.fat

This is exactly how the filename appears when you run the DIR command from

the Windows NT command prompt. However, when you boot the machine into MS-

DOS and run the DIR command, the filename appears as follows:

   longfi~1.fat

NOTE: NTFS partitions are not available under MS-DOS, so you cannot

perform this experiment using an NTFS partition.

The same result can also be achieved programmatically. Build and run the

following sample code on Windows NT:

Sample Code

-----------

   #include <windows.h>

   void main( )

   {

      WIN32_FIND_DATA fd;

      char buf[80];

      FindFirstFile( "long*", &fd );

      wsprintf( buf, "File name is %s", fd.cFileName );

      MessageBox( NULL, buf, "Test", MB_OK );

      wsprintf( buf, "Alternate file name is %s", fd.cAlternateFileName );

      MessageBox( NULL, buf, "Test", MB_OK );

   }

The first message box will read:

   File name is longfilename.fat

The second message box will read:

   Alternate file name is longfi~1.fat

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: Limits on Overlapped Pipe Operations

Article ID: Q115522

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   versions 3.1 and 3.5

----------------------------------------------------------------------

SUMMARY

=======

The Windows NT version 3.1 redirector allows only 17 outstanding overlapped

pipe operations at any given time. The Windows NT 3.5 redirector does

not have this restriction on overlapped pipe writes. However, the Windows

NT 3.5 redirector allows only 17 outstanding overlapped pipe reads at any

given time.

If the client uses overlapped I/O through the redirector, it is possible

for the client to become deadlocked. You may need to increase the number of

threads that the redirector uses for I/O; the same thing is true for the

server. If your application is doing a lot of I/O, you can avoid this

deadlock by creating extra threads and having them use non-overlapped I/O.

MORE INFORMATION

================

Increasing the workstation services MaxThreads parameter increases the

number of kernel threads that the redirector will create, thus allowing

more operations to be outstanding at any given time.

This parameter is located in:

   HKEY_LOCAL_MACHINE\SYSTEM\

      CurrentControlSet\

      Services\

      LanmanWorkstation\

      Parameters\

      MaxThreads

The parameter can be set from 0 to 255 (the default is 17).

Additional reference words: 3.10 3.50

KBCategory: Prg

KBSubcategory: BseFileio


INF: Accessing the Application Desktop from a Service

Article ID: Q115825

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.5

----------------------------------------------------------------------

SUMMARY

=======

Under Windows NT, version 3.1, if you want a service to have access to the

application desktop, you must run the service in the LocalSystem account. A

service process running in the LocalSystem account (or a process started

from such a service) can display message boxes, windows, and dialog boxes.

Processes that are running in the LocalSystem account are not terminated by

the system during logoff. A number of changes were made to Windows NT,

version 3.5, that affect the way Windows NT interacts with these services.

MORE INFORMATION

================

The following are new features of Windows NT, version 3.5, that affect

services:

 - The account of the logged in user is the only account granted access to

   the application desktop. The LocalSystem no longer has access.

 - Console and GUI applications started from a service process during a

   particular logon session are run on an invisible window station and

   desktop that are unique to that session. The window station and desktop

   are created automatically when the first application in the session

   starts; they are destroyed when the last application exits.

 - There is no way to make these invisible desktops visible.

 - If you want a service to interact with the logged-on user, the

   interaction must take place in one of the following ways:

    - From a thread that is impersonating the user when the first call to

      USER or GDI is made.

      -or-

    - By some other method, such as named pipes.

 - Services that need visible user notification to appear without having to

   impersonate the logged-on user can be arranged by calling MessageBox()

   with the new MB_SERVICE_NOTIFICATION flag. Using the

   MB_DEFAULT_DESKTOP_ONLY flag works as well.

 - Any output done to a window is not displayed or made available to  the

   application in any way. Attempts to read bits from the display results

   in a failure.

 - GUI services do not receive WM_QUERYENDSESSION/WM_ENDSESSION messages

   at logoff and shutdown; instead, they receive CTRL_LOGOFF_EVENT

   and CTRL_SHUTDOWN_EVENT events. These services are not terminated by the

   system at logoff.

Additional reference words: 3.50

KBCategory: Prg

KBSubcategory: BseService


INF: Clarification of SearchPath() Return Value

Article ID: Q115826

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The entry for "SearchPath()" in the "Win32 Programmer's Reference" says

that the return value will be one of the following:

 - The length (in characters) of the string copied to the buffer.

   -or-

 - 0 if the function fails [see "GetLastError()" in the "Win32 Programmer's

   Reference" for more information].

If the specified file is not found, then the return value is 0, but

the value retrieved by GetLastError() is not changed.

In order to distinguish the "file not found" condition from another

error (out of memory, invalid parameter, and so forth), call

SetLastError() with a value of NO_ERROR before calling SearchPath().

MORE INFORMATION

================

This behavior is by design. The recommended way to check the return

status for SearchPath() is:

   return value >  buffer length    buffer too small

   return value =  0                file not found or another error

   return value <= buffer length    file found

Handle the case where the return value is 0 as follows:

   TCHAR  szFilename[] = "MyFile.Txt";

   TCHAR  szPathname[MAX_PATH];

   LPTSTR lpszFilename;

   SetLastError( NO_ERROR );

   if( !SearchPath( NULL, szFilename, NULL, MAX_PATH, szPathname,

                    &lpszFilename ) )

   {

      if( GetLastError() == NO_ERROR )

         Display( "File not found." );

      else

         Display( "SearchPath failed!" );

   }

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseFileio


INF: Filenames Ending with Space or Period Not Supported

Article ID: Q115827

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

CreateFile() removes trailing spaces and periods from file and directory

names. This is done for compatibility with the FAT and HPFS file systems.

Problems can arise when a Macintosh client creates a file on a Windows NT

server. The code to remove trailing spaces and periods is not carried out

and the Macintosh user gets the correctly punctuated filename. The Win32

APIs FindFirstFile() and FindNextFile() return a filename that ends in a

space or in a period; however, there is no way to create or open the file

using the Win32 API.

Applications such as File Manager and Backup check to see whether the

filename ends with a space or period. If the filename does end in a space

or a period, then File Manager and Backup use the alternative name found in

WIN32_FIND_DATA.cAlternateFileName to create and open the file. Therefore,

the full filename is lost.

Additional reference words: 3.10 winfile ntbackup

KBCategory: Prg

KBSubcategory: BseFileio


INF: Getting Floppy Drive Information

Article ID: Q115828

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

To get the media type(s) supported by a floppy drive, it is necessary to

call CreateFile() to get a handle to the drive and then DeviceIoControl()

to get the information. However, if there is no floppy disk in the floppy

drive, the following message box may appear when CreateFile() is called for

drive A (\\.\a:):

   There is no disk in the drive. Please insert a disk into drive A:

When calling CreateFile(), be sure to use 0 for the access mode and

FILE_SHARE_READ for the share mode so that the user will not be prompted to

insert a floppy disk:

   CreateFile(

      szFileName,

      0,

      FILE_SHARE_READ,

      NULL,

      OPEN_ALWAYS,

      0,

      NULL

   );

Another way to avoid the message box prompt is to put

   SetErrorMode( SEM_FAILCRITICALERRORS );

before the call to CreateFile().

MORE INFORMATION

================

The following sample code is based on the code in the FLOPPY SDK sample,

but it simply displays the media type(s) supported by floppy drive A. The

code demonstrates one way to retrieve the supported media without requiring

you to insert a floppy disk in the drive.

Sample Code

-----------

#include <windows.h>

#include <stdio.h>

#include <winioctl.h>

DISK_GEOMETRY SupportedGeometry[20];

DWORD SupportedGeometryCount;

VOID

GetSupportedGeometrys( HANDLE hDisk )

{

   DWORD ReturnedByteCount;

   if( DeviceIoControl(

          hDisk,

          IOCTL_DISK_GET_MEDIA_TYPES,

          NULL,

          0,

          SupportedGeometry,

          sizeof(SupportedGeometry),

          &ReturnedByteCount,

          NULL

      ))

      SupportedGeometryCount = ReturnedByteCount /  sizeof(DISK_GEOMETRY);

   else SupportedGeometryCount = 0;

}

VOID

PrintGeometry( PDISK_GEOMETRY lpGeometry )

{

   LPSTR MediaType;

   switch ( lpGeometry->MediaType ) {

      case F5_1Pt2_512:

         MediaType = "5.25, 1.2MB,  512 bytes/sector";

         break;

      case F3_1Pt44_512:

         MediaType = "3.5,  1.44MB, 512 bytes/sector";

         break;

      case F3_2Pt88_512:

         MediaType = "3.5,  2.88MB, 512 bytes/sector";

         break;

      case F3_20Pt8_512:

         MediaType = "3.5,  20.8MB, 512   bytes/sector";

         break;

      case F3_720_512:

         MediaType = "3.5,  720KB,  512 bytes/sector";

         break;

      case F5_360_512:

         MediaType = "5.25, 360KB,  512 bytes/sector";

         break;

      case F5_320_512:

         MediaType = "5.25, 320KB,  512 bytes/sector";

         break;

      case F5_320_1024:

         MediaType = "5.25, 320KB,  1024 bytes/sector";

         break;

      case F5_180_512:

         MediaType = "5.25, 180KB,  512 bytes/sector";

         break;

      case F5_160_512:

         MediaType = "5.25, 160KB,  512  bytes/sector";

         break;

      case RemovableMedia:

         MediaType = "Removable media other than floppy";

         break;

      case FixedMedia:

         MediaType = "Fixed hard disk media";

         break;

      default:

         MediaType = "Unknown";

         break;

   }

   printf("    Media Type %s\n", MediaType );

   printf("    Cylinders %d, Tracks/Cylinder %d, Sectors/Track %d\n",

          lpGeometry->Cylinders.LowPart, lpGeometry->TracksPerCylinder,

          lpGeometry->SectorsPerTrack

         );

}

void main( int argc, char *argv[], char *envp[] )

{

   HANDLE hDrive;

   UINT i;

   hDrive = CreateFile(

                   "\\\\.\\a:",

                   0,

                   FILE_SHARE_READ,

                   NULL,

                   OPEN_ALWAYS,

                   0,

                   NULL

                   );

   if ( hDrive == INVALID_HANDLE_VALUE )

   {

      printf( "Open failed: %d\n", GetLastError() );

      ExitProcess(1);

   }

   GetSupportedGeometrys( hDrive );

   printf( "\nDrive A supports the following disk geometries\n" );

   for( i=0; i<SupportedGeometryCount; i++ )

   {

       printf("\n");

       PrintGeometry( &SupportedGeometry[i] );

   }

   printf("\n");

}

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: How to Gracefully Fail at Service Start

Article ID: Q115829

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

If an error occurs while your service is running or initializing

(SERVICE_START_PENDING) and you need to stop the service process, do the

following:

1. Clean up any resources that are being used (threads, memory, and so

   forth). You can optionally start sending a SERVICE_STOP_PENDING status.

2. Send out a SERVICE_STOPPED status from the last thread to terminate

   before it calls ExitThread().

3. Set SERVICE_STATUS.dwWin32ExitCode and/or

   SERVICE_STATUS.dwServiceSpecificExitCode to values that indicate why the

   service is stopping. If you return a value for the

   dwServiceSpecificErrorCode field, then the dwWin32ExitCode field should

   be set to ERROR_SERVICE_SPECIFIC_ERROR.

   The reason for setting these values is that if a service fails its

   operation, but returns an exit code of 0, the following error message is

   returned by default:

      Error 2140: An internal Windows NT error occurred

MORE INFORMATION

================

When the last service in the process has terminated (you may have multiple

services in the service process), the StartServiceCtrlDispatcher() call

in the main thread returns. The main routine should call ExitProcess()

because all of the services have terminated.

REFERENCES

==========

There is a termination sample in the "Win32 Programmer's Reference," in the

"Services" overview section (58.2.2), "Writing a ServiceMain Function."

This is a simple situation where the service process only consists of one

thread. This thread returns when it is ready to terminate, instead of

calling ExitThread().

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseService


INF: Specifying Serial Ports Larger than COM9

Article ID: Q115831

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

CreateFile() can be used to get a handle to a serial port. The "Win32

Programmer's Reference" entry for "CreateFile()" mentions that the share

mode must be 0, the create parameter must be OPEN_EXISTING, and the

template must be NULL.

CreateFile() is successful when you use "COM1" through "COM9" for the name

of the file; however, the message "INVALID_HANDLE_VALUE" is returned if you

use "COM10" or greater.

If the name of the port is \\.\COM10, the correct way to specify the serial

port in a call to CreateFile() is as follows:

   CreateFile(

      "\\\\.\\COM10",     // address of name of the communications device

      fdwAccess,          // access (read-write) mode

      0,                  // share mode

      NULL,               // address of security descriptor

      OPEN_EXISTING,      // how to create

      0,                  // file attributes

      NULL                // handle of file with attributes to copy

   );

NOTES: This syntax also works for ports COM1 through COM9. Certain boards

will let you choose the port names yourself. This syntax works for those

names as well.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseCommapi


INF: Services and Redirected Drives

Article ID: Q115848

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

When writing a service, do not use WNetAddConnection() to redirect drives

to remote shares, because the redirector does not allow the logged-on user

to see the server or enumerate the drive. Instead, use universal naming

convention (UNC) names whenever possible to redirect drives to remote

shares.

MORE INFORMATION

================

WNetAddConnection() creates a global symbolic link describing the drive.

Therefore, the user can change to the drive at the command prompt. However,

WNetOpenEnum(), WNetEnumResource, and the "net use" command fail to list

the drive connection that was created by the service. This happens because

the logged-on user does not have an active session to the remote

connection, so the redirector will not let the user see the remote server.

The File Manager calls GetDriveType() on each drive and puts up an icon

for each drive found. The File Manager creates an icon for redirected

drives created from a service because there is a global symbolic link to

that drive. However, the share name is not available. In addition, the

logged-on user cannot use File Manager to disconnect the drive because the

drive was created by the service, not the logged-on user.

If the service process is running in the Local System account, then only

that process or another process running in the Local System account can

call WNetCancelConnection() to disconnect the drive.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseService


INF: Determining the Maximum Allowed Access for an Object

Article ID: Q115945

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The AccessCheck() API call can be used to determine the maximum access to

an object allowed for a subject. (In this article, a subject means a

program running in a specific user's security context.) When using

AccessCheck() for this purpose, perform the following steps:

1. Obtain a security descriptor that has owner, group, and DACL

   information.

2. If you are not impersonating a client, obtain an impersonation token by

   calling ImpersonateSelf. This token is passed as the client token in the

   AccessCheck() call.

3. Create a generic mapping structure. The contents of this structure will

   vary depending on the object being used.

4. Call AccessCheck() and request "MAXIMUM_ALLOWED" as the desired access.

If the AccessCheck() call succeeds after the above steps have been

completed, the dwGrantedAccess parameter to AccessCheck() contains a

mask of the object-specific rights that are granted by the security

descriptor.

MORE INFORMATION

================

In most situations, you should not use this method of access determination.

If you need access to an object to perform a task, simply try to open the

object using the required access.

The AccessCheck() API is mainly intended for use with private objects

created by an application. However, it can be used with predefined objects.

The generic mapping values and specific rights for many of the predefined

objects (files and so forth) may be found in WINNT.H.

REFERENCES

==========

Please see the Security Overview in the "Win32 Programmer's Reference" and

the "Win32 SDK API Reference" for more information.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


PRB: AccessCheck() Returns ERROR_INVALID_SECURITY_DESCR

Article ID: Q115946

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

In certain cases, the AccessCheck() API fails and GetLastError() returns

the message "ERROR_INVALID_SECURITY_DESCR". This error message indicates

that the security descriptor passed to AccessCheck() was in an invalid

format.

CAUSE

=====

This is expected behavior for the AccessCheck() function. AccessCheck()

was designed for use by programs that create and maintain their own

security descriptors. These security descriptors would always have the

owner, DACL, and group information.

RESOLUTION

==========

If the security descriptor is indeed valid, you can eliminate the error

by ensuring that the security descriptor has been opened for access to

the following types of security information:

     OWNER_SECURITY_INFORMATION

     GROUP_SECURITY_INFORMATION

     DACL_SECURITY_INFORMATION

You can double check the validity of the security descriptor by calling

the IsValidSecurityDescriptor() API.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


INF: Adding Categories for Events

Article ID: Q115947

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The ReportEvent() API accepts a category ID as one of the arguments. The

"Microsoft Win32 Programmer's Reference" states that you can add your own

categories for events. This article shows you how to add categories that

will be recognized by the Event Viewer; however, the article assumes that

you already know how to create a message file and add an event source to

the registry. For information about basic event logging, please see the

logging sample in the Q_A\SAMPLES\logging directory on the "Win32 SDK" CD.

MORE INFORMATION

================

Just like events, category IDs are simply IDs in message file resources.

However, in order to use categories, the following two requirements must be

met:

 - The category IDs must be sequentially numbered, starting with a

   message ID of 1.

 - The event source entry in the registry must specify the category

   message file and the number of categories in the message file.

The first requirement is simply a matter of setting the MessageID entries

in the message file for the categories. If all of your categories are

listed at the top of the message file, you can assign the ID of 1 to the

first message. Each message after that automatically gets the next ID value

unless you specify otherwise in the MessageID entry.

The category entries in the registry are made by adding values to your

event key. Normally, your event log application key already contains

EventMessageFile and TypesSupported entries. You should add the following

two entries:

 - CategoryMessageFile

 - CategoryCount

The CategoryMessageFile entry is of type REG_EXPAND_SZ. It should be set to

the full path to the message file that contains the categories.

The CategoryCount entry is a REG_DWORD type. You should set this entry to

the number of categories in the message file specified in

CategoryMessageFile.

REFERENCES

==========

"Microsoft Win32 Programmer's Reference," Microsoft Corporation.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: Creating Access Control Lists for Directories

Article ID: Q115948

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The discretionary access control list (DACL) for a directory usually

differs from that of a file. When assigning security to a directory, you

are often specifying both the security for the directory and the security

for any contained files and directories.

A directory's ACL will normally contain at least two access control

entries (ACE):

 - An ACE for the directory itself and any subdirectories.

 - An ACE for any files in the directory.

If an ACE is to apply to object in the directory (subdirectories and

files), the ACE is marked as an OBJECT_INHERIT_ACE and/or a

CONTAINER_INHERIT_ACE. (In this article, a container means a directory.)

For example, when you use File Manager to set the security on a directory

to "Change (RWXD)(RWXD)," the directory's DACL contains the following two

ACEs:

   ACE1 (applies to files in the directory)

      ACE flags:   INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE

      Access Mask: DELETE | GENERIC_READ | GENERIC_WRITE |

                   GENERIC_EXECUTE

   ACE2 (applies to the directory and subdirectories)

      ACE flags:   CONTAINER_INHERIT_ACE

      Access Mask: DELETE | FILE_GENERIC_READ | FILE_GENERIC_WRITE |

                   FILE_GENERIC_EXECUTE

MORE INFORMATION

================

The ACE flags are part of the ACE header. The structure of an ACE header

can be found in the online help by searching on "ACE_HEADER".

In the above example, ACE1 applies only to contained files through the

INHERIT_ONLY_ACE flag. If INHERIT_ONLY_ACE is not specified in an ACE, the

ACE applies only to the current container.

NOTE: Adding one of these ACEs to a directory does not change the security

for any contained files or directories. The ACEs are only copied to files

and directories created after the ACEs have been added to the directory.

When adding your own security to files, it is easy to create a

combination that File Manager does not recognize as a "standard"

setting. This is shown in file manager as "special" security.

If you want to match the DACLs you create to those used by File Manager,

you can set the security of a file or directory in File Manager and then

check the DACLs and ACEs. A tool for this is provided as a sample called

"Check_SD" in the Win32 SDK. Check_SD can be found in the

Q_A\SAMPLES\CHECK_SD directory on the Win32 SDK CD.

REFERENCES

==========

 - "Microsoft Win32 Programmer's Reference," Microsoft Corporation.

 - "Microsoft Win32 SDK API Reference help file," Microsoft Corporation.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseSecurity


PRB: RegCreateKeyEx() Gives Error 161 Under Windows NT 3.5

Article ID: Q117261

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.5

----------------------------------------------------------------------

SYMPTOMS

========

A call to RegCreateKeyEx() is successful under Windows NT version 3.1, but

the call fails with error 161 (ERROR_BAD_PATHNAME) under Windows NT version

3.5.

The sample code below demonstrates this problem.

CAUSE

=====

This is by design. Windows NT version 3.1 allows the subkey to begin with a

backslash ("\"), however Windows NT version 3.5 does not. The subkey is

given as the second parameter to RegCreateKeyEx().

RESOLUTION

==========

Remove the backslash from the beginning of the subkey name.

MORE INFORMATION

================

In the sample code below, RegCreateKeyEx() fails with error 161 while the

string defined by SUBKEY_FORMAT_STRING begins with a backslash, but

succeeds if the initial backslash is removed.

Sample Code

-----------

   #include <windows.h>

   #include <stdio.h>

   #define SUBKEY_FORMAT_STRING \

   "\\SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s"

   void main(int argc, char *argv[])

   {

      DWORD dwErrorCode;

      char lpszSubKey[MAX_PATH];

      HKEY hKey;

      DWORD dwDisposition;

      sprintf( lpszSubKey, SUBKEY_FORMAT_STRING, argv[1] );

      printf( "Trying to open: %s\n", lpszSubKey );

      dwErrorCode = RegCreateKeyEx(HKEY_LOCAL_MACHINE,

                                   lpszSubKey,

                                   0,

                                   "",

                                   REG_OPTION_NON_VOLATILE,

                                   KEY_ALL_ACCESS,

                                   NULL, //Security

                                   &hKey,

                                   &dwDisposition );

      if (dwErrorCode != ERROR_SUCCESS)

         printf( "Code = %d.\n", dwErrorCode );

      RegCloseKey(hKey);

   }

NOTE: Double backslashes ("\\") are required in strings in C code to

represent a single backslash, since a backslash ordinarily indicates the

beginning of an escape sequence.

Additional reference words: 3.50

KBCategory: Prg

KBSubcategory: BseMisc


SAMPLE: World Coordinate Transform

Article ID: Q81721

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The sample WXFORM provides a demonstration of the new world coordinate

transforms. This sample displays a rectangle in world coordinates and a

matrix containing the transform values. Users can directly manipulate the

rectangle and see the effect on the transformation, or they can set the

transformation and see the effect on the rectangle.

This sample is included with the Microsoft Win32 Software Development

Kit (SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The program begins by setting the viewport origin to the

center of the client area. It then draws a rectangle in

world coordinate space from the point (0, 0) to the point

(100, 100). The user can directly manipulate this rectangle

by using the left and right mouse buttons. Specific actions

are described more fully in the "Direct Manipulation Help"

dialog box.

There is a second dialog box titled "World Transform." This

shows the values of the eM11, eM12, eM21, eM22, eDx, and eDy

fields in the XFORM structure retrieved by calling the

GetWorldTransform function. By choosing the buttons on this

dialog box, the user can cause a SetWorldTransform to occur

in the program.

There are three coordinate systems of interest in this

sample. The first one is the world coordinate system, which

is new to Win32. These points are ultimately mapped to the

second coordinate system, device coordinates, before being

painted in the window. This program must also use a third

coordinate system, screen coordinates, for certain

interactions with the mouse pointer.

There is a third dialog box titled "Mouse Position" that

shows the location of the cursor in all three of these

coordinate systems. The device coordinates are relative to

the upper-left corner of the client area. They are not

relative to the viewport origin.

Additional reference words: SetWorldTransform GetWorldTransform

ModifyWorldTransform 3.10

KBCategory: Ref

KBSubcategory: CodeSam GdiMisc


SAMPLE: AngleArc Demonstration Program

Article ID: Q81724

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The sample named ANGLE provides a demonstration of how the

new AngleArc() API works. The X, Y, and RADIUS parameters are all in the

world coordinate space. The start angle and sweep angle are floating-point

values and are interpreted as degrees.

This sample is included with the Microsoft Win32 Software Development

Kit (SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

This program presents a dialog box stretched across the top

of the window. The user can set the parameters for the

AngleArc() API by changing the values in the entry fields of this dialog

box. A button on the dialog box then allows the user to immediately see the

results of these values on the arc in the client area. If the values in the

entry field are invalid, the program will write out this information and

not draw the arc. The origin of the viewport is shifted down in the client

area so that it exists at the upper-left corner of the viewable area.

Additional reference words: 3.10

KBCategory:

KBSubcategory: CodeSam GdiDrw


SAMPLE: Demonstration of Using System Info API

Article ID: Q81849

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The GETSYS sample is an application which consists of a dialog box that

provides the user with an easy way to see the results of the following API

calls:

   GetSysColors()

   GetSystemDirectory()

   GetSystemInfo()

   GetSystemMetrics()

   GetSystemPaletteEntries()

   GetSystemTime()

This sample is included with the Microsoft Win32 Software Development

Kit (SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam GdiMisc


SAMPLE: StretchBlt Demonstration

Article ID: Q81850

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The STREBLT sample is an easy to use demonstration of the StretchBlt() API.

The program presents a dialog box on the top of the window, and through

this dialog box the user can manipulate the parameters to StretchBlt(). In

the main window, the source bitmap is displayed on the right half of the

window, and the destination bitmap is displayed on the left half.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The source and destination rectangles may be changed directly in the

dialog, or they may be changed by using the direct manipulation objects in

the two halves of the window. Clicking and dragging the mouse in the upper-

left corner moves the rectangles; clicking and dragging the mouse in the

lower-right corner sizes the rectangles. The source direct manipulation

object is temporarily erased before calling StretchBlt() so that the top

and left edges do not show in the destination image.

The raster operation for the StretchBlt() call may be changed by altering

the values in the right-most entry fields. The contents are interpreted to

be in hexadecimal. There is a combo box directly beneath these entry fields

that lists all of the standard raster operations. If the user selects a

standard ROP from this combo box, its contents are copied into the ROP

entry fields and are then used in the StretchBlt() call.

Several of the raster operations make use of a pattern in the destination

HDC. For this reason, the program also allows the user to select one of the

standard pattern brushes from a second combo box. This brush is selected

into the destination HDC just prior to making the StretchBlt() call.

The effect of the StretchBlt() call is also affected by the "StretchBlt()

mode" that has been set for the destination HDC. A third combo box allows

the user to select from any of the standard modes. The difference is most

easily observed when stretching from a large source rectangle to a small

destination rectangle.

The "Draw" button may be chosen at any time to cause the StretchBlt() call

to be made. This does not erase the background, so that the effect of

multiple ROPs on the HDC can be observed. Manipulating the source rectangle

also causes a StretchBlt() to occur without erasing the window. However,

manipulating the destination rectangle erases the destination half of the

window before the next StretchBlt() is called.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam GdiBmp


SAMPLE: Using Region-Related API Functions

Article ID: Q81874

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The REGIONS sample demonstrates various region-related API functions, and

allows a user to create rectangular, elliptic, and multi-polygon regions.

In addition, hit-testing a region and combining regions using the different

region-combination modes is demonstrated.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

When the program has started, create a region by choosing one of the items

in the Create submenu. At this point, items in the Options submenu will be

enabled, and hit-testing, inversion, and other actions can be performed on

the region.

When a second region is created, items in the Combine submenu will be

enabled. Choosing one of these items causes CombineRgn to be called with

the specified combine mode, and the two regions are merged into one.

It is possible to create up to three regions at a time. Items in the

Options submenu always apply to the most recently created (or combined)

region. The Erase item deletes all existing regions. Items in the Combine

submenu always apply to the two most recently created (or combined)

regions.

Additional reference words: PtInRegion CreateEllipticRgn GetRgnBox

CreatePolygonRgn CreateRectRgn SetRectRgn OffsetRgn FillRgn FrameRgn

KBCategory: Ref

KBSubcategory: CodeSam GdiDrw


SAMPLE: PlgBlt Demonstration

Article ID: Q81875

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The Win32 API offers a new function that will copy a bit image onto an

arbitrary parallelogram. Now, for the first time, application programs can

trivially rotate or shear bitmaps. The PLGBLT sample is an easy to use

demonstration of how this new API may be used.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The program presents a dialog box on top of the window that displays the

input parameters to the PlgBlt() function. By choosing the "New Src" or

"New Mask" button, the user can select a new bitmap for use as the source

bitmap or as the monochrome mask bitmap. The client area of the window is

divided into three regions. The region on the left contains the result of

the PlgBlt() operation. The region in the middle provides the source HDC,

and the region on the right provides the mask bitmap for the PlgBlt()

operation.

In each of the three regions, there is a "direct manipulation object." This

object may be picked up and moved by clicking the left mouse button in the

top-left corner and dragging. The three objects are restricted in their

response to user actions to correctly reflect the parameters to the

PlgBlt() function. The object in the mask region may be moved only. The

object in the source region may be moved or sized. The object in the

destination region may be moved, sized, sheared, or rotated. Please see the

WXFORM sample for more information on how this direct manipulation is

accomplished. Additional information on the WXFORM sample may be obtained

by querying on the word WXFORM in this knowledge base.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam GdiBmp


INF: General Overview of Win32s

Article ID: Q83520

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

SUMMARY

=======

The following is intended as a general introduction to Win32s. More

information can be found in the "Win32s Programmer's Reference" and by

querying for Knowledge Base articles on "Win32s".

MORE INFORMATION

================

General Overview

----------------

The Win32 API consists of the Window 3.1 (Win16) API, with types stretched

to 32 bits, plus the addition of APIs which offer new functionality, like

threads, security, services, and virtual memory. Applications developed

using the Win32 API are called "Win32 applications".

Win32s is a set of DLLs and a VxD which allow Win32 applications to run on

top of Windows or Windows for Workgroups version 3.1. Win32s supports a

subset of the Win32 API, some directly (like memory management) and some

through thunks to the 16-bit systems (particularly GDI and User). Win32s

contains function stubs for the APIs that are not supported, which return

ERROR_NOT_IMPLEMENTED. Win32s also includes 4 new APIs which support the

Universal Thunk (UT). For details on which API are supported under Win32s,

refer to the individual API entries in the help file "Win32 API Reference."

Among the new features gained from Win32 are structured exception handling

(SEH), FP emulation, memory-mapped files, named shared memory, and sparse

memory.

Win32 applications running on Windows 3.1 will generally be faster than

their Win16 equivalents on Windows 3.1, particularly if they are memory or

floating-point intensive. The actual speed improvement varies with each

application, because it depends on how often you cross the thunk layer.

Each call which uses a thunk is no more than 10 percent slower than a

direct call.

Binary Compatibility

--------------------

Win32s offers binary compatibility for Win32 application on Windows 3.1 and

Windows NT.

When you call a Win32 API, two options should be allowed:

 - Option A: Your code should allow for a successful return from the

   function call.

 - Option B: Your code should allow for an unsuccessful return from

   the function call.

For example, if the application is running under Windows 3.1 and a call is

made to one of the supported APIs, then the call returns successfully and

option A is executed. If the call is made while running under Windows NT,

the call again returns successfully and option A should be executed.

However, if running under Windows 3.1 and a Win32 API function is called

that is unsupported, then an error code is returned and option B should be

executed.

If, for example, option A were using a CreateThread() call, then option B

would be alternative code, which would handle the task using a single-

thread solution.

Programming Issues

------------------

Win32 applications cannot use DOS and BIOS interrupts; therefore, the

Win32s VxD has Win32 entries for each Interrupt 21 and the BIOS calls.

The Win32s DLLs may thunk to Win16 when a Win32 application makes a call.

The 32-bit parameters are copied from the 32-bit stack to a 16-bit stack

and the 16-bit entry point is called.

There are other semantic difference between Windows 3.1 and Win32. Windows

3.1 will run applications for Win32 nonpreemptively in a single, shared

address space, while Windows NT runs them preemptively in separate address

spaces. It is therefore important that you test your Win32 application on

both Windows 3.1 and Windows NT.

If you need to call routines that reside in a 16-bit DLL or Windows from 32-

bit code, you can do this using the Win32s Universal Thunk, RPC, or other

client-server techniques. For a description of UT, please see the "Win32s

Programmer's Reference" and the sample UTSAMPLE.

DDE, OLE, WM_COPYDATA, the clipboard, metafiles, and bitmaps can be used

between Win16 and Win32 applications on both Windows 3.1 and Windows NT.

Additional reference words: 1.10

KBCategory: Prg

KBSubcategory: W32s


SAMPLE: GetDeviceCaps() Demonstration Program

Article ID: Q83930

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The GETDEV sample uses a dialog box to display the results of calling the

GetDeviceCaps() API with all of the possible input parameters. Six of the

numeric results (TECHNOLOGY,LINECAPS, POLYGONALCAPS, TEXTCAPS, CLIPCAPS,

and RASTERCAPS) are expanded to show the constant string from WINGDI.H.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam GdiMisc


SAMPLE: PolyDraw Function Demonstration

Article ID: Q83931

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The POLYDRAW sample provides an easy-to-use demonstration of how the

PolyDraw() Win32 API works. The user can place points in the window with

the left mouse button, and move these points by dragging with the same

mouse button. The PolyDraw() curve is drawn dynamically to follow the

position of the new points.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

To use this program, click the left mouse button at miscellaneous places in

the client area. A Polyline() call shows exactly where the points were put.

By default, the type entered into the type array is PT_LINETO. This can be

changed to a PT_MOVETO type by holding down the SHIFT key. It can be

changed to a PT_BEZIERTO type by holding down the CTRL key. The resulting

purple curve shows the results. There will be no curve when the bezier

points do not come in groups of 4, 7, ... , (3n+1).

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam GdiDrw


PRB: Saving/Loading Bitmaps in .DIB Format on MIPS

Article ID: Q85844

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

In Win32, saving or loading a bitmap in .DIB file format is basically the

same as in Win16. However, care must be taken in DWORD alignment,

especially on the MIPS platform.

An exception occurs when loading or saving a bitmap on the MIPS platform.

In NTSD, the following error message is received:

   data mis-alignment

CAUSE

=====

A non-DWORD aligned actual parameter was passed to a function such as

GetDIBits().

The .DIB file format contains the BITMAPFILEHEADER followed immediately by

the BITMAPINFOHEADER. Notice that the BITMAPFILEHEADER is not DWORD

aligned. Thus, the structure that follows it, the BITMAPINFOHEADER, is not

on a DWORD boundary. If a pointer to this DWORD misaligned structure is

passed to the sixth argument of GetDIBits(), an exception will occur.

RESOLUTION

==========

To resolve this problem, copy the data in the structure over to a DWORD-

aligned memory and pass the pointer to the latter structure to the function

instead. See the sample code LOADBMP.C for detail.

MORE INFORMATION

================

The is a sample to illustrates this process. Refer to the LOADBMP.C file in

the MANDEL sample that comes with the Win32 SDK.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiBmp


INF: Using GetDIBits() for Retrieving Bitmap Information

Article ID: Q85846

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

When saving a bitmap in .DIB file format, the GDI function is used to

retrieve the bitmap information. The general use of this function and

the techniques for saving a bitmap in .DIB format are largely

unchanged; however, this article provides more details on the use of

the Win32 API version of the GetDIBits() function.

MORE INFORMATION

================

The function can be used to retrieve the following information:

 - Data in the BitmapInfoHeader (no color table and no bits)

 - Data in the BitmapInfoHeader and the color table (no bits)

 - All the data (BitmapInfoHeader, color table, and the bits)

The fifth and the sixth parameters of the function are used to tell

the graphics engine exactly what the application wants it to return.

If the fifth parameter is NULL, then no bits will be returned. If the

biBitCount is 0 (zero) in the sixth parameter, then no color table

will be returned. In addition, the biSize field of the

BitmapInfoHeader must be set to either the size of BitmapInfoHeader or

BitmapCoreHeader for the function to work properly.

Refer to the SAVEBMP.C file in the MANDEL sample for details. This sample

is included with the Win32 SDK.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiBmp


INF: Win32 Subsystem Object Cleanup

Article ID: Q89290

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The Win32 subsystem guarantees that all Win32 objects owned by a

process will be freed when an application terminates. To accomplish

this, the Win32 subsystem keeps track of who owns these objects; it

also keeps a reference count. Reference counts are used when the

object is owned by more then one process. For example, a memory mapped

file can be used to provide interprocess communication, where more

than one process would own that object. The subsystem must make sure

that the reference count is zero before the object can be freed.

Freeing of Win32 objects can occur at different times. In general, it

occurs at process termination, but for some objects, it occurs at thread

termination.

NOTE: When running Win32 applications with Windows 3.1 using the Win32s

environment, it is the responsibility of the Win32 application to ensure

that all allocated GDI objects are deleted before the program terminates.

This is different from the behavior of the application with Windows NT.

With Windows NT, the GDI subsystem cleans up all orhphaned GDI objects.

Because there is no GDI subsystem with Windows 3.1, this behavior is not

supported.

MORE INFORMATION

================

At process or thread termination, the Win32 subsystem searches its lists to

find objects owned by this process or thread. Those that are owned by the

terminating process or thread and whose reference counts will be set to

zero when the process or thread is fully terminated will be freed.

The freeing of objects is slightly different for Win32 applications running

under Win32s on Windows 3.1. The 16-bit objects (GDI objects, windows,

global memory, etc.) follow the same clean-up rules as Win16 applications

do under Window 3.1. The 32-bit objects, such as memory allocated via

VirtualAlloc(), shared memory via mapped file I/O, 32-bit modules, thunks

allocated on the fly (for hook procedures, wndprocs etc.) are all handled

by Win32s and freed at process termination.

The following is a list of Win32 objects. Note that it may not be complete.

   BASE: console, event, file (including file mapping), mutex,

         semaphore, thread, process, pipe (including named pipes)

   GDI:  device context (DC), bitmap, pen, brush, font, region, palette

   USER: window, cursor, icon, menu, accelerator table, desktop,

         DDE communication objects, DDE conversation objects, dialog

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: SubSys


INF: Transparent Blts in Windows NT

Article ID: Q89375

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

In order to perform a transparent blt in Microsoft Windows versions 3.0 and

3.1, the BitBlt() function must be called two or more times. This process

involves nine steps. (For more information on this process, see article

Q79212 in the Microsoft Knowledge Base.)

Windows NT introduces a new method of achieving transparent blts. This

method involves the use of the MaskBlt() function. The MaskBlt() function

lets you use any two arbitrary ROP3 codes (say, SRCCOPY and BLACKNESS) and

apply them on a pel-by-pel basis using a mask.

MORE INFORMATION

================

For this example, the source and target bitmaps contain 4 BPP. The call to

the MaskBlt() function is as follows:

   MaskBlt(hdcTrg,  // handle of target DC

                0,  // x coord, upper-left corner of target rectangle

                0,  // y coord, upper-left corner of target rectangle

               15,  // width of source and target rectangles

               15,  // height of source and target rectangles

           hdcSrc,  // handle of source DC

                0,  // x coord, upper-left corner of source rectangle

                0,  // y coord, upper-left corner of source rectangle

          hbmMask,  // handle of monochrome bit-mask

                0,  // x coord, upper-left corner of mask rectangle

                0,  // y coord, upper-left corner of mask rectangle

       0xAACC0020   // raster-operation (ROP) code

                );

The legend is as follows

   '.' = 0,

   '@' = 1,

   '+' = 2,

   '*' = 3,

   '#' = 15

Source Bitmap      Mask Bitmap        Target Bitmap      Result

------------------------------------------------------------------------

***+++***+++***    .......@.......    ###############    #######*#######

***+++***+++***    ......@@@......    ###############    ######***######

***+++***+++***    .....@@@@@.....    ##...........##    ##...+***+...##

+++***+++***+++    ....@@@@@@@....    ##...........##    ##..**+++**..##

+++***+++***+++    ...@@@@@@@@@...    ##...........##    ##.***+++***.##

+++***+++***+++    ..@@@@@@@@@@@..    ##...........##    ##+***+++***+##

***+++***+++***    .@@@@@@@@@@@@@.    ##...........##    #**+++***+++**#

***+++***+++***    @@@@@@@@@@@@@@@    ##...........##    ***+++***+++***

***+++***+++***    .@@@@@@@@@@@@@.    ##...........##    #**+++***+++**#

+++***+++***+++    ..@@@@@@@@@@@..    ##...........##    ##+***+++***+##

+++***+++***+++    ...@@@@@@@@@...    ##...........##    ##.***+++***.##

+++***+++***+++    ....@@@@@@@....    ##...........##    ##..**+++**..##

***+++***+++***    .....@@@@@.....    ##...........##    ##...+***+...##

***+++***+++***    ......@@@......    ###############    ######***######

***+++***+++***    .......@.......    ###############    #######*#######

Note that the ROP "AA" is applied where 0 bits are in the mask and the ROP

"CC" is applied where 1 bit is in the mask. This a transparency.

When creating a ROP4, you can use the following macro:

   #define ROP4(fore,back) ((((back) << 8) & 0xFF000000) | (fore))

This macro can be used to call the MaskBlt() function as follows:

   MaskBlt(hdcDest, xTrgt, yTrgt,

                          cx, cy,

              hdcSrc, xSrc, ySrc,

           hbmMask, xMask, yMask,

        ROP4(PATCOPY, NOTSRCCOPY)

                               );

This call would draw the selected brush where 1 bit appears in the mask and

bitwise negation of the source bitmap where 0 bits appear in the mask.

Additional reference words: 3.10 pixel

KBCategory: Prg

KBSubcategory: GdiBmp


INF: PSTR's in OUTLINETEXTMETRIC Structure

Article ID: Q90085

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The OUTLINETEXTMETRIC structure ends with four fields of type PSTR. The

four fields in question are not actually absolute pointers. They are

offsets from the beginning of the OUTLINETEXTMETRIC structure to the

strings in question, as the documentation indicates:

   otmpFamilyName

      Specifies the offset from the beginning of the structure to a

      string specifying the family name for the font.

   otmpFaceName

      Specifies the offset from the beginning of the structure to a

      string specifying the face name for the font. (This face name

      corresponds to the name specified in the LOGFONT structure.)

   otmpStyleName

      Specifies the offset from the beginning of the structure to a

      string specifying the style name for the font.

   otmpFullName

      Specifies the offset from the beginning of the structure to a

      string specifying the full name for the font. This name is

      unique for the font and often contains a version number or

      other identifying information.

The only difference between this structure in Windows 3.1 and Windows NT is

that the strings may be stored in either Unicode or ASCII under Windows NT.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiMisc


PRB: IsGdiObject() Is Not a Part of the Win32 API

Article ID: Q91072

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

There is no IsGdiObject() function in the Win32 API.

CAUSE

=====

The function was added to the Windows 3.1 API because passing a handle

to a non-GDI object to a GDI function causes a GP fault under Windows

3.0. Windows NT detects whether the APIs are passed an inappropriate

handle, so the function can return an error.

RESOLUTION

==========

IsGdiObject() is not needed on Windows NT.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiMisc


INF: Use of DocumentProperties() vs. ExtDeviceMode()

Article ID: Q92514

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Windows applications have used ExtDeviceMode() to retrieve or modify device

initialization information for printer drivers. The Win32 API introduces a

new function DocumentProperties() that applications can use to configure

the settings of the printer.

Note that ExtDeviceMode() calls DocumentProperties(); therefore, it is

faster for applications to use DocumentProperties() directly.

Specifying the DM_UPDATE mask allows an application to change printer

settings when using DocumentProperties(). Applications should be aware

that the GetProcAddress() function is now case sensitive.

Windows 3.x applications running on Windows NT (WOW) can call

ExtDeviceMode(). The spooler's ExtDeviceMode() entry is intended for WOW

use.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiPrn


INF: Using Device Contexts Across Threads

Article ID: Q94236

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

A window created with the CS_OWNDC style retains its device context (DC)

attributes across GetDC() calls.

However, the DC attributes are not retained if the GetDC() calls are called

from different threads. This is by design because DCs are thread-based. In

the Win32 user interface, if the calling thread is not the owner of the

window, then GetDC() returns a cache DC instead of the owned DC handle.

To save attributes across threads, one must create a routine to initialize

DC attributes, which is then called from threads not owning the given

window.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiDc


INF: 16 and 32 Bits-Per-Pel Bitmap Formats

Article ID: Q94326

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Windows NT supports the same bitmap formats as Microsoft Windows version

3.1, but includes two new formats: 16 and 32 bits-per-pel.

For DIBs (device independent bitmaps), the 16 and 32-bit formats contain

three DWORD masks in the bmiColors member of the BITMAPINFO structure (the

color table), instead of the array of RGBQUAD structures for 1-, 4-, and

8-bit formats). These masks specify which bits in the pel correspond to

which color.

The three masks must have contiguous bits, and their order is assumed to be

R, G, B (high bits to low bits). The order of the three masks in the color

table must also be first red, then green, then blue (RGB). In this manner,

the programmer can specify a mask indicating how many shades of each RGB

color will be available for bitmaps created with CreateDIBitmap().

For 16-bit bitmaps, CreateBitmap() defaults to the 5+5+5 format. The

formats 6+5+5 and 6+6+4 are also supported by this method.

MORE INFORMATION

================

Example

-------

The 5-5-5 format masks are:

   0x00007C00  red   (0000 0000 0000 0000 0111 1100 0000 0000)

   0x000003E0  green (0000 0000 0000 0000 0000 0011 1110 0000)

   0x0000001F  blue  (0000 0000 0000 0000 0000 0000 0001 1111)

For 16 bits-per-pel, the upper half of the DWORDs are always zeroed.

Usage

-----

When using 16 and 32-bit formats, there are also certain fields of the

BITMAPINFOHEADER structure that must be set to the correct values:

1. The biCompression member must be set to BI_BITFIELDS, or the DIB API

   will fail. This indicates that there are bit fields in the bitmap rather

   than encoded color indexes (as in 4- or 8-bit formats).

2. The biClrUsed member must be set to 3 (or 0, which means use the maximum

   number of color table entries for that format, which for 16 and 32 bits-

   per-pel is 3). The member names are a bit misleading in these cases,

   because the "color table" (the bmiColors entry of the BITMAPINFO

   structure) is not being used to store a list of colors, but 3 bit masks.

A technical note related to this subject from the Microsoft Multimedia

group is also available. It can be obtained from CompuServe in the WINEXT

and WINSDK forums. The filename is VFW.ZIP. In addition, the technote is

available by calling Microsoft Developer Services at (800) 227-4679,

extension 11771. The technical note is part of the Video for Windows

technical notes and describes how to create a display driver that supports

these new DIB formats, which are used by Video for Windows. The technical

note also includes definitions of installable image codecs.

Additional reference words: 3.10 technote

KBCategory: Prg

KBSubcategory: GdiBmp


SAMPLE: Demonstrating GDI and User APIs in Fractals

Article ID: Q94898

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The MANDEL sample demonstrates the Win32 GDI and USER API functions in the

setting of fractals.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The Mandelbrot Dream provides the following functions:

 - Drawing the Mandelbrot set and the corresponding julia set

 - Zooming into any of the set

 - MDI fractal drawing windows

 - Floating Point Math/Fix Point Math

 - Shifting color table entries

 - Changing palette entries and animating palatte aka color cycling

 - Loading/Saving bitmap created with special effect

 - Changing bitmap color with flood fill

 - Boundary tracing and creating a clip region out of it for

 - Creating special effects

 - Enumerating printers for printing

 - Loading RLE (or converting .bmp files to RLE) for playing in Viewer

 - Save the RLE in memory to disk.

NOTE: The sample also makes use of the LARGE_INTEGER library shipped with

the SDK for its fixed point math.

Draw the Mandelbrot Set and the Corresponding Julia Set

-------------------------------------------------------

1. To draw the Mandelbrot set, choose the Mandelbrot Set menu item from the

   Create menu to create a MDI child window to draw the set in if one has

   not already been created.

2. Then, choose either "use Fix Point math" or "use Floating Point math"

   from the Draw menu to decide if floating point or fixed point math is

   desired for calculation. Fix Point is faster, however you lose

   resolution sooner as you zoom in.

3. Also, choose the number of iterations from the Iteration menu item and

   choose Step from the Draw menu. The higher the number of iterations, the

   more detail is the picture but the slower to generate the picture. The

   step determines whether every scan line is drawn. The more scan lines it

   has, the better the picture but the slower to generate the picture.

4. To start drawing, choose Draw Set from the Draw menu.

5. To draw the Julia set, use the right mouse button to select a point in

   the Mandelbrot set (the drawing surface of the Mandlebrot window). A new

   Julia MDI window will be created. Then choose Draw Set from the Draw

   menu to start drawing.

6. The point selected with the right mouse button determines the complex

   constant to use for the Julia Set.

Zoom into Any of the Set

------------------------

1. To zoom in, click, drag and release with the left mouse button to

   describe the zoom in region.

   A new MDI child of the same type as the parent (Mandelbrot window or

   Julia window) will be created.

2. Choose Draw Set from the Draw menu to start drawing.

MDI Fractal Drawing Windows

---------------------------

Choose either Mandelbrot Set or Julia Set from the Create menu for creating

a new MDI window for drawing.

Or, use the left mouse button to describe a zoom in region in either a

mandelbrot or Julia MDI window for creating a new MDI window for drawing.

Or, click on the Mandelbrot window with the right mouse button for creating

a Julia MDI window corresponding to the mouse click position in the

Mandelbrot window.

Floating Point Math/Fix Point Math

----------------------------------

Choose the appropriate menu item ("Floating Point math" or "Fix Point

math") from the Draw menu. The Fix Point math uses 20.11 fixed point

integer arithmetic for calculation.

Shift Color Table Entries

-------------------------

Choose Shift from the Color menu or hit F10 to shift the color table entry.

The picture of the active MDI window will be updated.

Change Palette Entries and Animate Palatte (aka Color Cycling)

--------------------------------------------------------------

Choose Cycle from the Color menu or hit F11 to start color cycling the

picture.

The menu item will be grayed if the display device does not support palette

management. Currently, only the MIPs display driver supports that.

Load/Save Bitmaps Created with Special Effect

---------------------------------------------

Choose Load Bitmap from the Bitmap menu to load a bitmap into the active

child window, or choose Save Bitmap As to save the picture in the active

MDI child window.

Change Bitmap Color with Floodfill

----------------------------------

Choose Custom from the Color menu to select a color. Then the cursor will

be changed to a paint can over the active child window.  Click with the

left mouse button on the picture, the old color under the cursor will be

changed to the new color.

Trace Boundary and Create a Clip Region Out of it for Special Effect

--------------------------------------------------------------------

From any active Mandelbrot window, choose Set Mandelbrot Clip region from

the Region menu. The boundary of the escape region will be traced. The

region will then be selected as a clip region.

Thus, if you load a bitmap for display, the bitmap will only show through

the clip region. The new picture can then be saved.

To remove the clip region, choose Remove Clip Region from the Region menu.

Note, the boundary tracing algorithm may trace out a small island of only

several pixels and stop. If that happens, you might change the size of the

window or create another zoom window and trace again.

Enumerate Printers for Printing

-------------------------------

On start up, the Mandelbrot Dream will enumerate the printers and insert

the printers into the Print menu. Then selecting the printer on the Print

menu will print the picture in the active MDI window.

Load RLE (or Convert .BMP Files to RLE) to Play in Viewer

---------------------------------------------------------

Choose the Viewer item from the Create menu to create a viewer window or

bring any existing viewer window to the top. Select Load Bitmap(s) from the

File menu for loading RLE or bmp files into the memory from disk. Select

the Play or Play Continuously item from the Options menu for viewing.

For demonstration of what this functionality can do. Load the

.\rsc\julia.rle file and select Play Continuously. The Julia.rle is a

collections of the various julia sets along the boundary of escaping and

non-escaping points of the Mandelbrot Set.

Save the RLE in Memory to Disk

------------------------------

Choose the Viewer item from the Create menu to create a viewer window or

bring any existing viewer window to the top. Select Save Bitmap(s) from the

File menu for saving the RLE(s) from memory to disk.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam GdiMisc


SAMPLE: Demonstration of the Win32 Font API Functions

Article ID: Q94903

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The TTFONTS sample is an easy to use, powerful utility that allows the user

to explore the font system. There is a toolbar on top of the main frame

window with buttons that allow the following actions:

 - Enumerate all of the fonts installed for the display.

 - Get TEXTMETRIC & OUTLINETEXTMETRIC information.

 - Create a font based on an arbitrary LOGFONT structure.

 - Get "font data" by using the GetFontData() API.

 - Enumerate all of the fonts available to the default printer.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The program is designed to provide the user an easy interface to the API

calls related to the font system. It will not protect against meaningless

values, nor will it hide system oddities. Most of the buttons on the

toolbar are self explanatory and represent a single system API.

Pressing the EnumFonts button will show all of the face names listed

horizontally, and each of the fonts within that face name listed vertically

below it. TrueType fonts will be marked with a small colored "TT" bitmap.

Fonts that have the DEVICE_FONTTYPE bit on will be marked with a small

bitmap image of a printer. When the enumeration windows are showing the

user can click the left mouse button to copy the information about a

selected font into the LOGFONT and TEXTMETRIC dialogs. The user can dismiss

this window without changing the dialog boxes by clicking with the right

mouse button or typing any character.

The "Display" window is able to operate in any one of three modes.  These

are listed in the "Display" menu.  The first just writes "Hello" in the

middle of the screen, and it grids the background.  This is useful when

utilizing the lfEscapement and lfOrientation fields of the LOGFONT

structure. The second mode writes all of the glyphs between the tmFirstChar

and tmLastChar values stored in the TEXTMETRIC structure. The final mode is

used only for true type fonts. It calls GetFontData, finds the 'cmap'

table, and displays glyphs from the different ranges in this table.  Use

the horizontal scroll bar in the display window to step through the ranges.

NOTE: There is a font distributed on the Win32 SDK disk which covers more

than one thousand unicode characters. In order to use this application to

its full potential, you will want to install that font using the Control

Panel, Fonts item. The font is named L_10646.TTF.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam GdiFnt


SAMPLE: Enhanced Metafile Editor

Article ID: Q94904

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The MFEDIT sample demonstrates the Win32 enhanced metafile application

programming interface (API) functions.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The MFEDIT metafile editor provides the following functionalities:

 - Playing back and recording graphical device interface (GDI) calls.

 - Embedding a bitmap and enhanced metafile into another enhanced metafile

   with transformation.

 - Hit-testing against enhanced metafile records.

 - Random access playback.

 - Playing back metafile records one-by-one.

 - Selective recording of existing enhanced metafile records into a new

   enhanced metafile.

 - Drawing with pen, text, bezier, line, ellipse, rectangle, and embedding

   bitmap and enhanced metafile tools.

Playing Back and Recording GDI Calls

------------------------------------

 - To play back an existing enhanced metafile, from the File menu, choose

   Load Metafile, or click the Eject button to bring up the open file

   dialog box, and select the appropriate file. Then click the Play

   button to play the file on the drawing surface.

 - To record, click the Record button and draw on the drawing surface

   with the graphic tools provided. When done, click the Stop button.

   The GDI calls are recorded as C:\METAFX.EMF, where x is 0, 1, 2, 3,

   and so forth. If you want to save the metafile with a different

   name, choose Record Metafile As from the File menu.

   The new filename is used as the root for all metafiles recorded; 0,

   1, 2, and so forth are appended to the root name.

 - The default drawing tool is "pen". To select a different drawing tool,

   click the desired tool button in the control panel.

Embedding a Bitmap and Enhanced Metafile into Another Enhanced Metafile

with Transformation

-----------------------------------------------------------------------

 - Click the Record button. Select the bitmap or metafile tool and then

   embed the currently loaded bitmap or metafile as described in 7 below.

   When done, click the Stop button.

Hit-Testing Against Enhanced Metafile Records

---------------------------------------------

 - Play back an enhanced metafile by clicking the Playback button. Then

   choose Hit Test from the Edit menu. The cursor is changed to a cross

   hair when the mouse pointer is over the drawing surface.

 - Then click the graphic object played back in the drawing surface. The

   editor will search through the metafile, record after record, to find

   the record that corresponds to the object based on the mouse position.

   The search provides a visual cue by changing the graphic objects to red

   as it goes until it hits the corresponding object. If there is a hit,

   the record number is displayed on the control panel, a beep is heard,

   and a hit message is displayed on the bottom.

   When done, clear the Hit Test menu item.

Random Access Playback

----------------------

 - Click the number button in the control panel to play back a

   particular record. To access a non single-digit record, click the

   10+ button an appropriate number of times and then click the

   appropriate number button to bring the sum to the record desired.

Playing Back Metafile Records One-by-One

----------------------------------------

 - Click the Fast Forward button to play the metafile records one at a

   time.

Selective Recording of Existing Enhanced Metafile Records into a New

Enhanced Metafile

--------------------------------------------------------------------

 - Click the Record button and the appropriate number button for playing

   back selective metafile records in the drawing surface. The playback

   records will be recorded into the new metafile. When done, click the

   Stop button.

Drawing with Pen, Text, Bezier, Line, Ellipse, Rectangle and

Embedding Bitmap and Enhanced Metafile Tools

------------------------------------------------------------

 - The default pen is black. To change the pen color, choose the Pen menu

   item from the Options menu to select a color.

 - The default brush used by the Fill Rectangle and Fill Ellipse routines

   is black. To change the brush color, choose Brush from the Options menu

   to select a color.

 - The Text tool uses the default system font. To change the font, choose

   Font from the Options menu to change to a different font and font

   attributes.

 - The Bezier tool takes four points initially and three thereafter. To

   draw a bezier curve, select the Bezier tool and click the drawing

   surface three or four times to place the control points.

 - To embed a currently loaded bitmap, select the Bitmap tool and click

   three points on the drawing surface to describe where you want the

   bitmap located. The editor does the proper transformation on the

   bitmap and embeds the bitmap in the drawing.

 - To load a bitmap, choose Load Bitmap from the File menu and make the

   selection. The Bitmap tool optionally takes a mask bitmap. The mask

   bitmap must be a monochrome bitmap.

 - To load a mask bitmap, choose Load Mask Bitmap from the File menu to

   make the selection. Select a color bitmap, because the mask has the

   effect of resetting the mask to none.

 - To embed a currently loaded enhanced metafile, select the Embed

   Enhanced Metafile tool and click three points on the drawing

   surface to describe where you want the enhanced metafile located. The

   editor does the proper transformation on the metafile and embeds it

   in the drawing.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam GdiMeta


INF: Uniqueness Values in User and GDI Handles

Article ID: Q94917

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

User and GDI handles, are divided into two parts:

 - The lower 16 bits is an index into a system table of handle

   structures, which includes information such as the type of handle

   (window, menu, cursor, and so forth), as well as a value called the

   uniqueness.

 - The upper 16 bits contain the same uniqueness value.

The first time a handle is issued by the system, the uniqueness value is 0

(zero). It is incremented each time the handle is re-used. If you pass in a

value of 0xFFFF for the uniqueness, the client side (that is, USER32.DLL)

will look up the correct uniqueness value in shared memory and use the

correct handle.

This is important because it alleviates potential conflicts with re-used

handles. For instance, when a window is destroyed, its handle is reused by

the system. The uniqueness value prevents an old handle to a destroyed

window from being misinterpreted by the system as the handle to a new

object, which was given the same handle value.

MORE INFORMATION

================

In Win32s, use 0x0000 in the upper 16 bits for the uniqueness.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrMisc


INF: Advantages of Device-Dependent Bitmaps

Article ID: Q94918

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

A DDB (device-dependent bitmap) is much faster than a DIB (device

independent-bitmap) to BitBlt(). For this reason, it is often a good

strategy under Win32 (as well as under Windows 3.1) to create a DDB from a

DIB when caching or calling *Blt() functions.

The slight drawback of memory overhead for the DDB is handled well by

Win32. Under Windows 3.1, the DDB memory could be marked as discardable.

Under Win32, the memory will be paged out if system resources become tight

(at least until the next repaint); if the memory is marked as

PAGE_READONLY, it can be efficiently reused, [see VirtualProtect() in the

Win32 application programming interface (API) Help file].

However, saving the DDB to disk as a mechanism for transfer to other

applications or for later display (another invocation) is not recommended.

This is because DDBs are driver and driver version dependent. DDBs do not

have header information, which is needed for proper translation if passed

to another driver or, potentially, to a later version of the driver for the

same card.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiBmp


INF: DEVMODE and dmSpecVersion

Article ID: Q96282

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The dmSpecVersion field of the DEVMODE structure is intended for printer

driver use only; no application programs should test this field. The

purpose of this field is for new printer drivers to be able to recognize

and handle DEVMODE structures created according to previous DEVMODE

structure specification.

MORE INFORMATION

================

The DEVMODE structure is used for printer and (occasionally) display

drivers when initializing. This structure is tied to the driver--not the

operating system. The dmSpecVersion field does not allow an application to

determine which platform (Windows version 3.1, Windows on Windows, Win32)

the application is running in.

When an application fills a DEVMODE structure, it should set the

dmSpecVersion field to DM_SPECVERSION. This identifies the version of the

DEVMODE structure the application is generating.

If the application is querying to understand an unknown device, then

special attention should be paid to the dmFields, dmSize, and dmDriverExtra

fields. These fields are a reliable means of understanding what fields in

the DEVMODE structure are readable.

The DEVMODE structure consists of public and private parts. The

dmSpecVersion field applies to the public part. Any previously defined

fields are not altered when the DEVMODE specification is updated--more

fields are merely added to the end of the structure. This can mean fields

used in the previous specification are ignored in a later specification.

This functionality is managed by one bitfield describing what fields a

driver actually uses. The new drivers just switch off the obsolete fields.

Applications using DEVMODE should always use the dmSize and dmDriverExtra

fields for allocating/storing/manipulating the structure. These fields

define the sizes of the public and private parts of the structure,

respectively.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiPrn


SAMPLE: Demonstration of Printing with Windows NT

Article ID: Q96405

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The PRINTER sample does the following:

 - Shows how to print on Windows NT, using both the CreateDC() and the

   PrinterDlg() methods for acquiring a printer HDC. The user is

   allowed to print different graphics objects, as well as a complete

   device font set. An Abort dialog box is also implemented.

 - Provides complete device capabilities for all printers and the

   display.

 - Provides information (levels 1 and 2) returned by a call to

   EnumPrinters().

 - Shows how to enumerate fonts for a particular DC.

 - Illustrates differences between the various mapping modes.

 - Demonstrates GDI functionality.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. The samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

The main application window contains a menu and a toolbar. The various

submenus allow for:

    Submenu             Description

    -------            -----------

    Print               Calls CreateDC to get a device context for the

                        selected printer in the toolbar combo box, and

                        then prints the current graphics options to

                        this DC.

    PrintDlg            Calls PrintDlg to retrieve a device context for

                        a printer, then prints out current graphics

                        options to this DC.

    GetDeviceCaps       Retrieves device capabilities for the device

                        currently selected in the toolbar combo box, and

                        displays them in a dialog box.

    EnumPrinters        Retrieves levels 1 and 2 information returned

                        by EnumPrinters, and displays this information

                        in a dialog box.

    GetPrinterDriver    Returns levels 1 and 2 information returned by

                        GetPrinterDriver (for the currently selected

                        printer) and displays this information in a

                        dialog box.

    EnumPrinterDrivers  Returns levels 1 and 2 information returned by

                        EnumPrinterDrivers, and displays this information

                        in a dialog box.

    Refresh             Refreshes the contents of the toolbar combo box

                        (changes made in Print Manager are reflected

                        by this).

    About               Application information dialog box.

    Mapping Modes       User chooses between different mapping modes.

    Graphics            User chooses different primitives to display.

    Pen                 User can configure size, color, and style of

                        the drawing pen.

    Brush               User can configure size, color, and style of

                        the drawing brush.

    Text color          User can configure color used to draw fonts.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam GdiPrn


SAMPLE: Fractal Screen Saver Demonstration

Article ID: Q96409

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The SCRNSAVE screen saver sample draws the Mandelbrot Set on the screen,

then saves the picture in the path as specified in the configuration dialog

box. The default path is C:\FRACTAL.BMP.

When it is done, the screen saver animates the palette (for palette-

manageable devices only.)

Users can specify the area of the Mandelbrot Set to draw as well as the

number of iterations.

This sample is included with the Microsoft Win32 Software Development Kit

(SDK) for Windows NT. Samples are divided into two groups: samples

(optionally) installed into the \MSTOOLS\SAMPLES directory, and small

samples available on the CD in the \Q_A\SAMPLES directory.

MORE INFORMATION

================

To install the screen saver, copy the executable FRACTAL.SCR to the

WINNT\SYSTEM32 directory. Then install the screen saver in Control Panel.

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: CodeSam GdiScrsav


INF: Memory Handles and Icons

Article ID: Q99360

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Memory handles are not globally sharable among processes. Handles for

icons, cursors, windows, and so forth, are not global handles but are

handles into an index into the server-side handle table (the handle is

actually an index into the server-side's handle table). Thus, some objects

can be shared between processes -- but probably shouldn't be, for

concurrency reasons.

GDI-related objects, however, are stored in a client-side handle table,

which is translated to a handle value in a server-side table on every

client-server transition. Thus, there are some objects that can be shared

(USER-related objects) and some that can't be shared (BASE/KERNEL and GDI).

MORE INFORMATION

================

There are three types of handles in the system:

 - Handles to objects that the executive (object manager) knows

   about. These are assigned on a per-process basis but each access to

   these objects goes through the executive.

 - Handles that are maintained by the Win32 subsystem server (USER

   objects, including icons and cursors) and are therefore sharable.

   Please note that the allowed behavior of shared USER objects is

   subject to change in future releases of Windows NT. Thus, care

   should be taken when using these handles.

 - Handles that are maintained by the Win32 subsystem client, and

   therefore are valid only in the context of the process that created

   it (GDI objects). These handles differ from the first type of

   handles listed in that you cannot call handle manipulation

   functions, such as DuplicateHandle() an WaitForSingleObject(), or

   use the security facilities on these objects.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrMisc


INF: Use 16-Bit .FON Files for Cross-Platform Compatibility

Article ID: Q100487

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

The AddFontResource() function installs a font resource in the GDI font

table. Under Windows NT, the module can be a .FON file or a .FNT file.

Under Windows 3.1, the module must be a .FON file. When using Win32s,

AddFontResource() passes its argument to the Win16 AddFontResource, and

therefore .FON files should be used for portability.

In addition, when running under Windows NT, the module can be either a

32-bit "portable executable" or a 16-bit .FON file. However, if the same

Win32 executable is run under Win32s, the call to AddFontResource() fails

if the .FON is not in 16-bit format. Therefore, for compatibility across

platforms, use 16-bit .FON files. These can be created using the Windows

3.1 Software Development Kit (SDK).

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiFnt


INF: Tracking Brush Origins in Windows NT

Article ID: Q102353

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

When programming for Windows NT, it is no longer necessary to keep track of

brush origins yourself. GDI32 keeps track of the brush origins by

automatically recognizing when the origin has been changed. In Windows, you

have to explicitly tell GDI to recognize the change by calling

UnrealizeObject() with a handle to the brush. When a handle to a brush is

passed to UnrealizeObject() in Windows NT, the function does nothing.

In Windows 3.1, the default brush origin is the screen origin. In Windows

NT, the default origin is the client origin.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiPnbr


INF: Calculating the TrueType Checksum

Article ID: Q102354

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

To calculate a TrueType checksum:

1. Sum all the ULONGS in the .TTF file, except the checkSumAdjust

   field (which contains the calculated checksum). Note that TrueType

   files are big-endian, while Windows and Windows NT are little-endian,

   so the bytes must be swapped before they are summed.

2. Subtract the result from the magic number 0xb1b0afba.

MORE INFORMATION

================

Example

-------

1. Open the SYMBOL.TTF distributed with Windows NT. It is 64492 bytes

   long.

2. Step through the 16123 ULONGS, summing each one, except for the

   checkSumAdjust field for the file (which in this case is

   0xa7a81151).

3. Subtract the result from 0xb1b0afba. The result is 0xa7a81151.

The TrueType font file specification is available from several sources,

including the Microsoft Software Library (query on the word

TTSPEC1).

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiFnt


INF: Symbolic Information for System DLLs

Article ID: Q103862

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The debugging information for the system dynamic-link libraries (DLLs)

is contained separately in files with a .DBG extension. The Win32 SDK

setup, SETUPSDK, will install the following .DBG files by default in

<SYSTEMROOT>\SYMBOLS\DLL:

   ADVAPI32.DBG           OLECLI32.DBG

   COMDLG32.DBG           OLESVR32.DBG

   CRTDLL.DBG             RASAPI32.DBG

   DLCAPI.DBG             RPCNS4.DBG

   GDI32.DBG              RPCRT4.DBG

   INETMIB1.DBG           SHELL32.DBG

   KERNEL32.DBG           USER32.DBG

   LMMIB2.DBG             VDMDBG.DBG

   LZ32.DBG               VERSION.DBG

   MGMTAPI.DBG            WIN32SPL.DBG

   MPR.DBG                WINMM.DBG

   NDDEAPI.DBG            WINSTRM.DBG

   NETAPI32.DBG           WSOCK32.DBG

   NTDLL.DBG

Note that these files are not installed by the alternative Win32 SDK

install method, MANUAL.BAT. Therefore, WinDbg will warn that symbol

information cannot be found for each of the system DLLs called by the

debuggee.

These .DBG files can be manually installed by copying them from the

SDK CD. For x86, they are located in \SUPPORT\DEBUG\I386\SYMBOLS\DLL.

For MIPS, they are located in \SUPPORT\DEBUG\MIPS\SYMBOLS\DLL. Note

that there are more than 200 .DBG files in each of these directories.

MORE INFORMATION

================

There are also debugging versions of the system DLLs that can be

installed by using SWITCH.BAT, which is located on the CD in

\SUPPORT\DEBUGDLL. Refer to page 11 of the "Getting Started" manual

and the batch file itself for more information.

Additional reference words: 3.10

KBCategory: Setins

KBSubcategory: Setins


INF: Creating a Logical Font with a Nonzero lfOrientation

Article ID: Q104010

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

To create a font that writes in a direction other than left to right, an

application should specify a nonzero lfEscapement in the LOGFONT structure

that is passed to CreateFontIndirect(). This method works under Windows NT

regardless of the graphics mode of the device context.

To create a font where the characters themselves are rotated, the

application should specify a nonzero lfOrientation in the LOGFONT structure

that is passed to CreateFontIndirect(). However, this setting is ignored in

Windows NT unless the graphics mode is set to GM_ADVANCED.

Therefore, to successfully create a logical font with a nonzero

lfOrientation, use

   SetGraphicsMode( hDC, GM_ADVANCED )

to set the graphics mode of the device context to GM_ADVANCED.

MORE INFORMATION

================

The TTFONTS sample program is a good way to quickly and easily see the

effects of the lfEscapement and lfOrientation fields. However, TTFONTS does

not set the graphics mode of its test window HDC to GM_ADVANCED. As a

result, the lfOrientation field apparently is ignored. It is easy to modify

the DISPLAY.C module of TTFONTS in order to set the graphics mode of the

window HDC to GM_ADVANCED.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiFnt


PRB: StreBlt Sample Causes Windows NT to Stop Responding

Article ID: Q104834

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

When you run the STREBLT sample, Windows NT may stop responding (hang).

STATUS

======

We are researching this problem and will post new information here in the

Microsoft Knowledge Base as it becomes available.

MORE INFORMATION

================

Steps to Reproduce Problem

--------------------------

1. Build the StreBlt sample using the supplied makefile.

2. The sample displays a dialog box for the main window. There are

   three drop-down list controls titled StretchBltMode, Pattern, and

   Standard ROPs. Select the following in these drop-down lists:

      StretchBltMode    BLACKONWHITE

      Pattern           NULL_BRUSH

      Standard ROPs    PATPAINT

At this point, Windows NT stops responding.

Additional reference words: 3.10

KBCategory: Prg

KBSubCategory: GdiBmp


FIX: SetCaret API May Not Work Correctly in Win32 Applications

Article ID: Q105733

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The SetCaret() API does not work correctly in multithreaded Win32

applications. Code with the following logic fails:

Thread 1: Creates a window and starts another thread.

Thread 2: Uses an API to synchronize the two threads' "Input State,"

attempts to write to the window of Thread 1, and then tries to set the

caret through SetCaret().

STATUS

======

Microsoft has confirmed this to be a problem in Windows NT and Windows NT

Advanced Server version 3.1. This problem was corrected in the latest U.S.

Service Pack for Windows NT and Windows NT Advanced Server version 3.1. For

information on obtaining the Service Pack, query on the following word in

the Microsoft Knowledge Base (without the spaces):

   S E R V P A C K

Additional reference words: 3.10

KBCategory: Prg

KBSubCategory: GdiCurico


INF: ClipCursor() Requires WINSTA_WRITEATTRIBUTES

Article ID: Q106384

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The documentation for ClipCursor() states that the calling process must

have WINSTA_WRITEATTRIBUTES access to the window station. However, this

permission does not have to be enabled programmatically because the system

always grants the Local Login SID (the interactive user)

WINSTA_WRITEATTRIBUTES access, regardless of the permission groups to which

the user belongs.

MORE INFORMATION

================

The following code shows how to confine the cursor to the application

window during WM_ACTIVATE processing. Note that the clip cursor region must

be restored to its previous state each time the application deactivates.

Sample Code

-----------

   static RECT rcOldClip;

    .

    .

    .

      case WM_ACTIVATE:{

         short fActive = LOWORD( wParam );

         if( fActive ){

            RECT rcNewClip;

            /* Record the area in which the cursor can move. */

            GetClipCursor( &rcOldClip );

            /* Get the dimensions of the application's client area. */

            GetClientRect( hWnd, &rcNewClip);

            /* Convert to screen coordinates. */

            MapWindowPoints( hWnd, NULL, (LPPOINT)&rcNewClip, 2 );

            /* Confine the cursor to the application's window. */

            ClipCursor( &rcNewClip );

        }

        else{

            /* Restore the cursor to its previous area. */

            ClipCursor( &rcOldClip );

        }

        break;

    }

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiCurico


INF: Retrieving DIBs from the Clipboard

Article ID: Q106386

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Retrieving a DIB (device-independent bitmap) from the clipboard can take

significantly more time than retrieving a bitmap from the clipboard. The

difference stems from the fact that a bitmap is a GDI object and a DIB is a

global memory object.

MORE INFORMATION

================

When SetClipBoardData() is passed a global memory handle, as it is when it

is passed a handle to a DIB, all the data gets copied into the Win32 server

and put into a sharable section of memory. When the DIB is retrieved with

GetClipBoardData(), the shared memory is mapped into the application's

virtual address space and the memory handle is cached. Any subsequent calls

to GetClipBoardData() return quickly, because the memory does not have to

be remapped.

In contrast, when retrieving a bitmap with GetClipBoardData(), only a

handle is created, because a bitmap is a GDI object.

When CloseClipboard() is called, all of the cached handles to shared memory

and GDI objects are deleted.

Rather than reopening the clipboard, it is a good idea to keep a local copy

of anything retrieved from the clipboard if the item will be used again

after the clipboard has been closed. In general, data should be retrieved

from the clipboard only when the application is doing a paste or if the

application is a clipboard viewer processing a WM_DRAWCLIPBOARD message.

The data for a GDI object exists on the server side. In other words,

bitmaps and DDBs (device-dependent bitmaps) exist in the Win32 subsystem

address space. Only the handles of GDI objects are private to an

application. Therefore, to make a bitmap or a DDB accessible to another

application, only a call to DuplicateHandle() is needed.

Note that even though it is faster to retrieve a DDB from the clipboard, it

is still recommended to put a DIB on the clipboard rather than a DDB.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrClp


DOCERR: LoadCursorFromFile() and SetSystemCursor() Are Missing

Article ID: Q108234

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The following application programming interfaces (APIs) are included in

Windows NT 3.1, but are not documented.

MORE INFORMATION

================

LoadCursorFromFile()

--------------------

HCURSOR LoadCursorFromFile( lpszFilename )

LPWSTR lpszFilename; /* address of file name of cursor file */

Loads and creates a cursor from the specified file and returns a handle to

the new cursor. When multiple cursors reside in the specified file, the

cursor that is most appropriate for the current display device is loaded.

The API returns NULL for failure.

The file may be in either .CUR or .ANI format.

If the high word of lpszFilename is zero, lpszFilename is assumed to be a

system cursor ID. Then the [Cursors] entry in WIN.INI is searched for the

file associated with the name of the system cursor.

System cursor names and their associated IDs are:

   "Arrow"         OCR_NORMAL

   "IBeam"         OCR_IBEAM

   "Wait"          OCR_WAIT

   "Crosshair"     OCR_CROSS

   "UpArrow"       OCR_UP

   "Size"          OCR_SIZE

   "Icon"          OCR_ICON

   "SizeNWSE"      OCR_SIZENWSE

   "SizeNESW"      OCR_SIZENESW

   "SizeWE"        OCR_SIZEWE

   "SizeNS"        OCR_SIZENS

   "SizeAll"       OCR_SIZEALL

   "No"            OCR_SIZENO

   "AppStarting"   OCR_APPSTARTING

For example, if WIN.INI contains the following

   [Cursors]

      Arrow = "arrow.ani"

then LoadCursorFromFile( (LPWSTR)OCR_NORMAL ) will load the cursor from the

file ARROW.ANI.

SetSystemCursor()

-----------------

BOOL SetSystemCursor( hCursor, dwCursorId )

HCURSOR hCursor;   /* handle of cursor */

DWORD dwCursorId;  /* cursor ID */

Replaces the contents of the system cursor specified by dwCursorId with the

contents of the cursor specified by hCursor and then destroys hCursor. The

API returns TRUE for success.

Valid cursor IDs are:

   OCR_NORMAL

   OCR_IBEAM

   OCR_WAIT

   OCR_CROSS

   OCR_UP

   OCR_SIZE

   OCR_ICON

   OCR_SIZENWSE

   OCR_SIZENESW

   OCR_SIZEWE

   OCR_SIZENS

   OCR_SIZEALL

   OCR_SIZENO

   OCR_APPSTARTING

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiCurico


INF: Querying Device Support for MaskBlt

Article ID: Q108929

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The Win32 documentation for MaskBlt() states:

   Not all devices support the MaskBlt function. An application should call

   the GetDeviceCaps function to determine whether a device supports this

   function.

To query support for MaskBlt(), an application should query the device for

BitBlt support by passing RC_BITBLT constant to GetDeviceCaps().

MaskBlt() implements transparent blts in Windows NT. For more information,

query on the following words in the Microsoft Knowledge Base

   transparent and blts and Windows NT

GDI implements this application programming interface (API) by calling

BitBlt(). Because BitBlt() is implemented at the driver level, applications

that calls MaskBlt() should check for BitBlt() support on the device.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiBmp


DOCERR: DeviceCapabilitiesEx Not Implemented in Windows NT 3.1

Article ID: Q110702

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The "Win32 Help" help file correctly states the following about

DeviceCapabilitiesEx():

   The DeviceCapabilitiesEx function is not implemented for the first

   release of Windows NT. It is exported, so that applications based on

   pre-release versions of Windows NT will load, but nothing happens

   when it is called. Applications should use the DeviceCapabilities

   function.

However, the hard copy documentation gives the complete specification for

this function, as if it were already implemented. This is a documentation

error in the Win32 Programmers Reference.

NOTE: The Microsoft Developer's Network (MSDN) CD includes these manuals,

including this mistake, as well. The help files are generally more up to

date because the printed materials must be completed at an earlier date

than the help files.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiMisc


INF: Win32s 1.1 Limitations

Article ID: Q114340

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s, version 1.1

----------------------------------------------------------------------

SUMMARY

=======

The following is a list of limitations of Win32s, not including the

complete list of unsupported Win32 APIs.

MORE INFORMATION

================

 - Thread creation is not supported.

 - Win32s uses the Windows 3.1 nonpreemptive scheduling mechanism.

 - Win32s has a shared address space, so instance data for dynamic link

   libraries (DLLs) is not supported.

 - Win32 processes should be started from a Win16 application through

   WinExec() or Int 21 4B. LoadModule() does not start a Win32 process.

 - Win32 applications cannot use the EM_SETHANDLE or EM_GETHANDLE messages

   to access the text in a multiline edit control. These messages allow the

   sharing of local memory handles between an application and USER.EXE. In

   Win32s, an application's local heap is 32-bit, so USER.EXE cannot

   interpret the local handle. To read and write multiline edit control

   text, an application should use WM_GETTEXT and WM_SETTEXT.

   Text for multiline edit controls is stored in the 16-bit local heap in

   DGROUP, which is allocated by Windows 3.1 for the WIN32S.EXE stub that

   is loaded before each Win32 application is loaded. This means that the

   size of edit control text is limited to somewhat less than 64K.

 - The CBT hook thunks do not copy back the contents of structures, so any

   changes will be lost.

 - Win32 applications should not call through return from SetWindowsHook().

   SetWindowsHook() returns a pointer to the next hook in the chain. To

   call this function, the application is supposed to call DefHookProc()

   and pass a pointer to a variable where this address is stored. Because

   Win32s simulates the old hook API in terms of the new, SetWindowsHook()

   actually passes back a hook handle, not a function pointer.

 - Win32s requires all modules to be linked with 4K alignment. Temporarily,

   the loader supports 64K as well.

 - Integer ID must be a 16-bit value.

 - PostMessage() and PeekMessage() do not thunk structures. These functions

   do not allocate space for repacking structures, because there is no way

   to know when to free up the space.

 - Private application messages should not use high word of wParam. Win32s

   uses Windows 3.1 to deliver window messages. For unknown messages,

   wParam is truncated to make it fit into 16 bits. Therefore, Win32

   applications should not put 32-bit quantities into the wParam of

   privately defined messages, which are unknown to the thunk layer.

 - Win32s allows a Win32 application to allocate memory at a specific

   address; however, because of the shared address space on Windows 3.1,

   this is more likely to fail under Win32s.

 - DDE messages are always posted, not sent, except for two:

   WM_DDE_INITIATE and WM_DDE_ACK, responding to the former. The sent form

   of WM_DDE_ACK is different from the posted form. When sent, no thunking

   of lParam is necessary when going between 16- and 32-bit format.

   However, when posting, the lParam parameter is repacked as two DWORDs

   into private memory, allocated by COMBO.DLL (or by USER.DLL in Windows

   NT). The thunk layer makes this distinction through the InSendMessage()

   function. Therefore, a Win32 application should not do anything in the

   processing of a WM_DDE_INITIATE message that would cause the return code

   from InSendMessage() to be FALSE.

 - The following DDE messages are handled differently by different

   applications under Windows and Win32:

      WM_DDE_ACK

      WM_DDE_ADVISE

      WM_DDE_DATA

      WM_DDE_EXECUTE

      WM_DDE_POKE

   Because of widening of handles, there is not enough space in the Win32

   message parameters for all the Windows 3.1 data. Win32 applications are

   required to call helper functions that package the data into memory

   (DDEPACK structure) referenced by a special handle. Win32s implements

   the helper functions, and allocates the DDEPACK structure on behalf of

   16-bit code when necessary.

   As with other memory handles shared through DDE, there are rules

   concerning who frees the memory allocated by these helper routines:

      lParam = PackDDElParam(...)

      if( PostMessage(...,lParam) )

         receiving window has obligation of freeing memory

         lParam now invalid for this process

      else

         FreeDDElParam(...,lParam)

   A Win32s hook procedure that has called CallNextHookProc() should not

   use the lParam handle if the latter's return code indicates that the

   message has been processed. The hooks that could possibly process a DDE

   message are:

      WH_DEBUG

      WH_HARDWARE

      WH_KEYBOARD

      WH_MOUSE

      WH_MSGFILTER

      WH_SYSMSGFILTER

   In each case, if the hook proc (and therefore CallNextHookEx()) returns

   a non-zero value, the message was either discarded or processed.

   WndProcs should not use the lParam of a DDE message after handing it off

   to any other message API, because they cannot know if the message has

   been processed and therefore must assume that it has been.

 - WDEB386 does not support FreeSegment() for 32-bit segments. Win32s

   Kernel Debugger support depends on it.

 - Resource table size for PE is limited to 32K (not including the resource

   data).

 - SetClipbrdData() must be used only with global handle. Otherwise the

   data can not be accessed by other applications.

 - Win32s supports printing exactly as Windows 3.1 does. Win32s does not

   add beziers, paths, or transforms to GDI; to let applications use these

   features on PostScript printers, you must call the Escape() function

   with the appropriate escape codes.

   Applications link to Windows 3.1 printer drivers through the

   LoadLibrary() and GetProcAddress() APIs, which have special support for

   this purpose. There is no mechanism allowing a Win32 application to link

   to a 16-bit DLL.

 - Win32s does not support the following GDI escape codes:

      BANDINFO                 ;24

      GETSETPAPERBINS          ;29

      ENUMPAPERMETRICS         ;34

      EXTTEXTOUT               ;512

      SETALLJUSTVALUES         ;771

 - Integer atoms must be in the range 0 - 0x3FFF. This restriction is

   necessary for the current implementation of the window properties API

   thunks: SetProp(), GetProp(), RemoveProp(), EnumProps(), and

   EnumPropsEx(). Integer atoms above 0x4000 are rejected by the thunk

   layer.

 - Arrays must fit in 64K after converting to 16-bit format. An array

   passed to a function such as SetCharABCWidths() or Polyline() must fit

   within 64K after its elements have been converted to their 16-bit form.

   Its 32-bit form may be bigger than 64K.

 - Temporarily, all Windows 3.1 APIs that return void return 1 to the Win32

   application.

 - Win32 child window ID's must be sign-extended 16-bit values. This

   excludes the use of 32-bit pointer values as child ID's.

 - When calling PeekMessage(), a Win32 application should not filter any

   messages for Windows 3.1 internal window classes (button, edit,

   scrollbar, and so forth). The messages for these controls are mapped to

   different values in Win32, and checking for the necessity of mapping is

   time-consuming.

 - The dwThreadId parameter in SetWindowsHookEx() is ignored. The

   dwThreadId is translated to hTask in Windows 3.1. There's a bug in

   Windows 3.1 where if hTask!=NULL, the call may fail. This needs further

   investigation.

 - Floating point (FP) emulation by exception cannot be performed in 16-bit

   applications. When tasks are switched between applications, the CR0-EM

   bit state is not preserved, in order to support 32-bit application FP

   emulation by exception without breaking the existing 16-bit applications

   that use FP instructions. The CR0-EM bit is assumed to be cleared during

   execution of 16-bit-application FP instructions. Upon executing a 16-bit-

   application FP instruction, the bit is cleared and reset when switching

   back to a 32-bit application. The CR0-EM bit management is done in the

   Win32s VxD, thus disabling the possibility of getting an int 7 exception

   just by setting the CR0-EM bit in a 16-bit application.

 - EndDialog() nResult parameter is sign-extended. Applications specify the

   return value for the DialogBox() function by way of the nResult

   parameter to the EndDialog() function. This parameter is of type "int",

   which is 32-bit in Win32s. However, this value is thunked through to the

   Windows 3.1 EndDialog() function, which truncates it to a 16-bit value.

   Win32s sign-extends the return code from DialogBox().

 - GetClipBox() returns SIMPLEREGION(2) and COMPLEXREGION(3). Because

   Windows NT is a preemptive multitasking system, GetClipBox() on Windows

   NT never returns SIMPLEREGION(2); the reason for this is that between

   the time the API was called and the time the application gets the

   result, the region may change. Win32s can return both SIMPLEREGION(2)

   and COMPLEXREGION(3).

 - PeekMessage() filtering for posted messages (hWnd==-1) is not supported.

   The hWnd is replaced with NULL.

 - Message queue length is limited to Windows default: 8 (or whatever the

   length) was set by DefaultQueueSize=n in WIN.INI. This limit may be

   increased in the future to a larger size, but there will always be a

   limit.

 - GetFileTime() and SetFileTime() process only the lpLastWriteTime

   parameter and return an error if this parameter is not supplied.

 - The precision of the time of a file is 2 seconds (DOS limitation).

 - CommDlg does not support private dialog templates. The dialog templates

   need to be converted back and forth between 16- and 32-bit formats.

   Until Win32s 1.15, private dialog templates are not supported.

 - GetPrivateProfileString() returns an error when the lpszSection

   parameter is NULL instead of giving all the section names in the

   inifile, as it does under Windows NT.

 - TLS locations are the same in all processes for a specific DLL. This is

   because Win32s does not support instance data for DLLs. The TLS

   locations are unique per DLL. Each DLL should call TlsAlloc() only once

   per index if it is running under Win32s. The index returned is then

   valid for all Win32 processes. The DLL can maintain several indices.

 - GlobalCompact() is thunked through to the Windows 3.1 GlobalCompact().

   This API has no effect on memory allocated through VirtualAlloc(), which

   does not come from the Win3.1 global heap.

 - GetVolumeInformation() does not support the Volume ID.

 - GetFileInformationByHandle() and the CRT fstat() that uses it are not

   supported. Both are supported in Win32s, version 1.15. The

   dwFileAttribute of GetFileInformationByHandle() is always zero. This

   also causes fstat() to return an st_mode of read/write regardless the

   actual attribute.

 - CreatePolyPolygonRgn() requires a closed polygon, as it does under

   Windows 3.1. If the polygons are not closed, the Windows NT call closes

   the polygons for you. In Windows 3.1/Win32s, if the polygons are not

   closed, the call does not create the region correctly or returns an

   error for an invalid parameter.

 - Win32s does not support DIB_PAL_INDICES option for SetDIBits(). It will

   be supported in future release. DIB_PAL_PHYSINDICES and

   DIB_PAL_LOGINDICES are not supported either.

 - The WH_FOREGROUNDIDLE hook type is not supported. Windows 3.1 does not

   provide the necessary support.

 - The brush styles BS_DIBPATTERNPT and BS_PATTERN8X8 are not supported and

   cause an error to be returned.

 - The hFile in DLL and PROCESS events is not supported under Win32s

   because there is no support for duplicating file handles between

   processes (basically an MS-DOS limitation).

   There are two ways to access the image bytes: ReadProcessMemory() or

   open the file in compatibility mode (the name is provided in

   lplpImageName).

 - Under Windows NT, NetBIOS keeps a different name table for each process.

   On Win32s, there is only one NetBIOS name table for the system. Each

   name (group or unique) added by a process is kept in a doubly linked

   list. Through NCBRESET or by destroying the process, we delete all the

   names that were added by the process. Win32s does not implement the full

   NetBIOS 3.0 specification, which has a separate name table per process.

 - When calling 32-bit code from 16-bit code with UT (for example, from

   interrupt routine) the stack must be at least 10K. The interrupt routine

   must ensure that the stack will be big enough.

 - Get/SetThreadContext() can be called only from within an exception. At

   all other times, this function returns FALSE and the error code is set

   to ERROR_CAN_NOT_COMPLETE.

 - CreateProcess() PROCESS_INFORMATION is not supported for 16-bit

   applications. A valid structure must be passed to CreateProcess(), but

   the function fills all the fields with NULLs and zeroes.

 - Win32s does not support NT event mechanism; therefore, the ncb_event

   field in NCB structure is not supported.

 - CreateFileMapping() does not support SEC_NOCACHE nor SEC_NOCOMMIT. The

   call fails with ERROR_INVALID_PARAMETER.

 - Always use device-independent bitmaps for color bitmaps. Win32s supports

   the four Win32 "device-dependent" bitmap APIs. These are device-

   dependent in the sense that the bitmap bits are supplied without a color

   table to explain their meaning.

      CreateBitmap

      CreateBitmapIndirect

      GetBitmapBits

      SetBitmapBits

   These are well-defined and fully supported for monochrome bitmaps. For

   color bitmaps, these APIs are not well defined and Win32s relies on

   Windows 3.1 for their support. This means that an application cannot

   know the format of the bits returned by GetBitmapBits() and should not

   attempt to directly manipulate them. The values returned by

   GetDeviceCaps() for PLANES and BITSPIXEL, and the values returned by

   GetObject() for a bitmap, do not necessarily indicate the format of the

   bits returned by GetBitmapBits().It is possible for the GDI DIB APIs to

   be unsupported on some displays. However, it is now rare for display

   drivers to not support DIBs. The one case where it is not uncommon to

   encounter a lack of DIB support is with printer drivers, which may not

   support the GetDIBits() API, though most do support the SetDIBits() API.

   Win32s does not transform the bits in any way when passing them on to a

   Windows 3.1 API. When running an application that creates a device-

   dependent bitmap through CreateBitmap() or CreateBitmapIndirect(), be

   aware that the bits it is passing in may not be in the right format for

   the device. Windows NT takes care of this by treating the bits as a DIB

   whose format is consistent with the PLANES and BITSPIXEL values; but

   Win32s simply passes them through.

 - After calling FindText(), an application cannot directly access the

   FINDREPLACE structure. When an application calls the common dialog box

   function FindText(), it passes a FINDREPLACE structure. The FindText()

   dialog box communicates with the owner window through a registered

   message, in which the lParam points to the structure. The thunks repack

   this structure in place, so that unless the application is processing

   the registered message, it should not access the structure.

 - Subclassing a window that owns a FindText() common dialog does not work.

   The FindText() thunk repacks the FINDREPLACE structure in place. This

   means that 32-bit WndProcs cannot subclass 16-bit owners of FindText()

   dialog boxes without likely trashing four bytes beyond the end of the

   structure, because the 32-bit FINDREPLACE is four bytes bigger than the

   16-bit version.

   For 32-bit owners of the dialog box, there are also problems. Whenever

   the structure might be referenced by 16-bit code, it needs to be in the

   16-bit format. However, when the FindText() dialog box terminates, the

   structure needs to be in 32-bit format so that the application can read

   the final values. The dialog box indicates to its owner that it is about

   to be destroyed by sending the commdlg_FindReplace message with the

   FR_DIALOGTERM bit set in the Flags field of the FINDREPLACE structure.

   After sending this message, the FindText() dialog does not reference the

   structure anymore, so that the commdlg_FindReplace thunk leaves it in 32-

   bit format.

   The problem occurs when the owner has been subclassed. Once the message

   has moved to the 32-bit side, the structure is not reconverted to 16-

   bit. Suppose the dialog box owner was subclassed by a 16-bit WndProc,

   which was in turn subclassed by a 32-bit WndProc. When a message is sent

   to the owner, it will first go to 32-bit, then to 16-bit, then back to

   32-bit to the original WndProc:

   1. 16->32 message sent to 32-bit subclasser (repacked to 32-bit)

   2. 32->16 message sent to 16-bit subclasser (not repacked)

   3. 16->32 message sent to 32-bit original WndProc (not repacked)

   The 16-bit subclasser cannot interpret the message parameters because

   they are in 32-bit format. Between steps 2 and 3, the structure is not

   repacked because it's already in 32-bit format.

   When a Win32 application calls FindText(), allocate the following:

   1. A structure that contains the htask of WIN32S.EXE

   2. The original 32-bit FINDREPLACE pointer

   3. A count of the number of times the structure has been thunked without

      returning

   4. A 16-bit format copy of FINDREPLACE

   The structure is repacked into the 16-bit version and this copy is

   passed to Windows. The count is initially zero. When the

   commdlg_FindReplace message is sent in either direction (16->32 or

   32->16), repack the structure on the stack. If it was originally 32-bit,

   increment the count. When returning, unpack the structure and, if

   originally 32-bit, decrement the count. If the Flags field of the

   structure has the FR_DIALOGTERM bit set, the structure is originally 32-

   bit, and the count goes to 0 on a return, then repack the structure back

   to the original 32-bit space.

Additional reference words: 3.10 1.10

KBCategory: Prg

KBSubcategory: Win32s


INF: Printing Offset, Page Size, and Scaling with Win32

Article ID: Q115762

---------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

---------------------------------------------------------------------

The Win32 documentation for the Escape() function says that the

GETPHYSPAGESIZE, GETPRINTINGOFFSET, and GETSCALINGFACTOR escapes are

obsolete, but it fails to mention the recommended way to get this

information.

The information retrieved by all three escapes can now be retrieved by

calling GetDeviceCaps() with the appropriate index:

 - For the GETPHYSPAGESIZE escape, the indexes to be used with

   GetDeviceCaps() are PHYSICALWIDTH and PHYSICALHEIGHT.

 - For GETPRINTINGOFFSET, the indexes are PHYSICALOFFSETX and

   PHYSICALOFFSETY.

 - For GETSCALINGFACTOR, the indexes are SCALINGFACTORX and SCALINGFACTORY.

All six new indexes are defined in the file WINGDI.H, though they are

missing from the GetDeviceCaps() documentation.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: GdiPrn


INF: Accessing the Application Desktop from a Service

Article ID: Q115825

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.5

----------------------------------------------------------------------

SUMMARY

=======

Under Windows NT, version 3.1, if you want a service to have access to the

application desktop, you must run the service in the LocalSystem account. A

service process running in the LocalSystem account (or a process started

from such a service) can display message boxes, windows, and dialog boxes.

Processes that are running in the LocalSystem account are not terminated by

the system during logoff. A number of changes were made to Windows NT,

version 3.5, that affect the way Windows NT interacts with these services.

MORE INFORMATION

================

The following are new features of Windows NT, version 3.5, that affect

services:

 - The account of the logged in user is the only account granted access to

   the application desktop. The LocalSystem no longer has access.

 - Console and GUI applications started from a service process during a

   particular logon session are run on an invisible window station and

   desktop that are unique to that session. The window station and desktop

   are created automatically when the first application in the session

   starts; they are destroyed when the last application exits.

 - There is no way to make these invisible desktops visible.

 - If you want a service to interact with the logged-on user, the

   interaction must take place in one of the following ways:

    - From a thread that is impersonating the user when the first call to

      USER or GDI is made.

      -or-

    - By some other method, such as named pipes.

 - Services that need visible user notification to appear without having to

   impersonate the logged-on user can be arranged by calling MessageBox()

   with the new MB_SERVICE_NOTIFICATION flag. Using the

   MB_DEFAULT_DESKTOP_ONLY flag works as well.

 - Any output done to a window is not displayed or made available to  the

   application in any way. Attempts to read bits from the display results

   in a failure.

 - GUI services do not receive WM_QUERYENDSESSION/WM_ENDSESSION messages

   at logoff and shutdown; instead, they receive CTRL_LOGOFF_EVENT

   and CTRL_SHUTDOWN_EVENT events. These services are not terminated by the

   system at logoff.

Additional reference words: 3.50

KBCategory: Prg

KBSubcategory: BseService


INF: Distributed Computing Environment (DCE) Compliance

Article ID: Q92515

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Remote Procedure Call (RPC) is one part of the OSF Distributed Computing

Environment (DCE) model. The following background information comes from

the introduction to RPC in the "Remote Procedure Call Programmer's Guide

and Reference":

   The design and technology behind Microsoft RPC is just one part of a

   complete environment for distributed computing defined by the Open

   Software Foundation (OSF), a consortium of companies formed to define

   the components of a complete environment that supports distributed

   computing. The OSF requests proposals for standards, accepts comments on

   the proposals, votes whether to accept the standards and promulgates

   them.

Generally speaking, Microsoft has tested interoperability with DCE RPC

1.0.1. We are DCE RPC compliant, not compliant with the whole DCE. For

example, there is no support for the OSF DCE Core Services (that is,

Directory Service, Security Service, Time Service, and so on) or the OSF

DCE Extended Services (that is, Distributed File Service, Diskless Support

Service, Personal Computer Integration Service, and so on).

MORE INFORMATION

================

Microsoft RPC, which interoperates with connection-oriented DCE RPC, is

supported on MS-DOS, Windows, and Windows NT. MS-DOS and Windows support

RPC clients. Windows NT supports both RPC clients and servers.

DCE has been certified using TCP/IP and UDP/IP. Microsoft RPC under MS-DOS

supports LAN Manager version 2.1 TCP only. Under Windows, TCP is supported

from any vendor that is compliant with the Windows Sockets specification.

Under Windows NT, we support the TCP packaged in the product. In

addition to those protocols, which are of interest to people looking

at interoperability, Microsoft RPC also supports NetBIOS and Named

Pipes.

The OSF will be sponsoring inter-vendor tests early in 1993. Microsoft

intends to attend. At the current time, DEC is the only vendor shipping

DCE. Microsoft has tested interoperability with Ultrix and VMS machines.

Microsoft RPC is part of the Win32 SDK. The customer has the right to

freely distribute run times with applications if the run time is not

already distributed with the operating system.

REFERENCE

=========

There is a header file and sample on ftp.microsoft.com that addresses DCE

compatibility (and there is a patch for Windows NT 3.1). These can be found

in \developer\devtools\win32sdk\samples\dce_rpc.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: NtwkRpc


PRB: WSAAsyncSelect() Notifications Stop Coming

Article ID: Q94088

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

I have set a WSAAsyncSelect() call to notify me of read (FD_READ) and

disconnection (FD_CLOSE). When a read call is posted on my message

queue, I continually read from the socket until there are no more

characters waiting. After each read, I use a select() call to determine

if more data needs to be read. However, after a while, the notifications

stop coming. Why is this?

CAUSE

=====

The message queue must be cleared of extraneous notification messages

for each read notification message.

RESOLUTION

==========

Call WSAAsyncSelect( sockt, hWnd, 0, 0) to clear the message queue for

each read notification.

MORE INFORMATION

================

Sample Code

-----------

WSA_READCLOSE:

  if (WSAGETSELECTEVENT( lParam ) == FD_READ) {

    FD_ZERO( &readfds );

    FD_SET( sockt, &readfds);

    timeout.tv_sec = 0;

    timeout.tv_usec = 0;

    /* Clear the queue of any extraneous notification messages. */

    WSAAsyncSelect( sockt, hWnd, 0, 0);

    while (select(0, &readfds, NULL, NULL, &timeout) != 0) {

      recv(sockt, &ch, 1, 0);

      }

    /* Reset the message notification. */

    WSAAsyncSelect( sockt, hWnd, WSA_READCLOSE, FD_READ | FD_CLOSE);

    }

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: NtwkWinsock


INF: Writing a Telnet Client

Article ID: Q95866

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Windows NT provides a Telnet client service, which allows developers to

easily write applications that connect with hosts that have a Telnet daemon

process running.

To use the Telnet client service, the workstation must have the TCP/IP

protocol installed properly. To start the Telnet service, type

   net start telnet

at a command shell prompt, or use the Services application in the Control

Panel to start the Telnet service.

The interface to the Telnet service is through the Win32 communications

APIs (application programming interfaces). Instead of opening "COM1:" or

"COM2:", the special device name TELNET is opened. Handling the device is

the same as handling a standard communications port (some functionalities

are not supported, such as setting baud rates, DCB settings, and so forth).

For an example of how to use the Telnet client service, see the TTY sample

in the Win32 Software Development Kit (SDK) under the \MSTOOLS\SAMPLES\COMM

subdirectory.

MORE INFORMATION

================

Before connecting to a remote host, the IP address of both the remote host

and the local host must be entered properly in the hosts file, located in

the \%SYSTEMROOT%\SYSTEM32\DRIVERS\ETC subdirectory.

Additional reference words: 3.10 TCPIP

KBCategory: Prg

KBSubcategory: NtwkWinsock


INF: NetBIOS Name Table and NCBRESET

Article ID: Q95944

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The Windows NT NetBIOS implementation conforms to the IBM NetBIOS 3.0

specifications, with several enhancements discussed in this article.

MORE INFORMATION

================

Name Table

----------

Under Windows NT, the name table is maintained on a per-process basis,

which means that names added by one process are not visible by a different

process. This also means that for two processes to establish a session,

both processes must register two different NetBIOS names. However, sessions

can be established by two threads in the same process using the same

NetBIOS name.

NCBRESET

--------

The IBM NetBIOS 3.0 specifications defines four basic NetBIOS environments

under the NCBRESET command. Win32 follows the OS/2 Dynamic Link Routine

(DLR) environment. This means that the first NCB issued by an application

must be a NCBRESET, with the exception of NCBENUM. The Windows NT

implementation differs from the IBM NetBIOS 3.0 specifications in the

NCB_CALLNAME field.

In the "IBM Local Area Network Technical Reference," under the section on

NetBIOS 3.0, the NCB_CALLNAME field is defined as the following:

   REQ_SESSIONS at NCB_CALLNAME+0 (1-byte field)

   The number of sessions requested by the application program.

   If zero, the default of 16 is used.

   REQ_COMMANDS at NCB_CALLNAME+1 (1-byte field)

   The number of commands requested by the application program.

   If zero, the default of 16 is used.

   REQ_NAMES at NCB_CALLNAME+2 (1-byte field)

   The number of names requested by the application program. This

   does not include a reservation for NAME_NUMBER_1.

   If zero, the default of 8 is used.

   REQ_NAME_ONE at NCB_CALLNAME+3 (1-byte field)

   A request to reserve NAME_NUMBER_1 for this application program.

   If 0, NAME_NUMBER_1 is not requested.

   If not 0, NAME_NUMBER_1 is desired to be reserved for this

   application.

Under the Windows NT implementation, the REQ_COMMANDS (NCB_CALLNAME+1)

field is ignored. Instead, an application is bound by the amount of memory

the process can allocate.

For more information on the differences between the Windows NT

implementation and the IBM NetBIOS 3.0 specifications, see "The NetBIOS

Function" in the "Win32 API Reference" Help file.

For more information on version 3.0 of NetBIOS, contact IBM and order the

"IBM Local Area Network Technical Reference."

Additional reference words: 3.10 NCBRESET

KBCategory: Prg

KBSubcategory: NtwkNetbios


INF: Using RPC Callback Functions

Article ID: Q96781

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The standard remote procedure call (RPC) model has a server containing one

or more exported function calls, and a client, which calls the server's

exported functions. However, Microsoft's implementation of RPC defines

callbacks as a special interface definition language (IDL) attribute

allowing a server to call a client function.

Callbacks can be used only in the context of a server call. Thus, a server

may call a client's callback function only when the server is performing a

client's remote procedure call (before it returns from processing). For

example:

                CLIENT                SERVER

                ------                ------

       Client makes RPC call. --->

                                <--- Server calls callback procedure.

Client returns from callback. --->

                                <--- Server calls callback procedure.

Client returns from callback. --->

                                <--- Server returns from original RPC call.

MORE INFORMATION

================

Callbacks are declared in the RPC .IDL file and defined in the source of

the client. The following demonstrates how callbacks are declared and

defined:

[ SAMPLE.IDL ]

[

   uuid(9FEE4F51-0396-101A-AE4F-08002B2D0065),

   version(1.0),

   pointer_default( unique )

]

{

 void RPCProc( [in, string] unsigned char *pszStr );

 [callback] void CallbackProc([in,string] unsigned char *pszStr);

}

[ SAMPLEC.C (Client)]

/*

   Callback RPC call (initiated from server, executed on client).

*/

void CallbackProc( unsigned char *pszString )

{

  printf("Call from server, printed on client: %s", pszStr );

}

[ SAMPLES.C (Server)]

/*

   "Standard" RPC call (initiated from client, executed on server).

   Makes a call to client callback procedure, CallbackProc().

*/

void RPCProc( unsigned char *pszStr )

{

  printf("About to call Callback() client function.."

  CallbackProc( pszStr );

  printf("Called callback function.");

}

In the makefile for the sample, the "-ms_ext" switch must be used for the

MIDL compile. For example:

   midl -ms_ext -cpp_cmd $(cc) -cpp_opt "-E" sample.idl

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: NtwkRpc


INF: RPC Can Use Multiple Protocols

Article ID: Q100009

------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

------------------------------------------------------------------

Microsoft Remote Procedure Call (RPC) does not rely on a single protocol.

An RPC server can be written to use all available protocols on the server,

and a client can be written in the same manner. Thus, the server or client

does not have to know which protocols it supports explicitly.

Currently supported RPC protocols are:

   ncacn_dnet_nsp (DECNet)

   ncacn_ip_tcp   (TCP/IP)

   ncacn_nb_nb    (NetBIOS over NetBEUI)

   ncacn_nb_tcp   (NetBIOS over TCP)

   ncacn_np       (Named Pipes)

   ncalrpc        (LPC)

Note: All protocols are connection-oriented. Mailslots (or other

connectionless methods) are not supported.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: NtwkRpc


INF: Tuning Sessions, Names, and NCBs for NetBIOS Applications

Article ID: Q101268

--------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

--------------------------------------------------------------------

The Names, Sessions, and NCB parameters in Microsoft LAN Manager were

exposed through the PROTOCOL.INI file and applied for various NetBIOS

applications. The Windows NT NetBIOS redirector uses TDI for transport

related communications. Various NetBIOS applications need to change the

default values for Names, Sessions and NCBs. Under Windows NT, there is no

interface or Registry parameter with which to set or changes these values.

In order to change these values for a NetBIOS application, the application

needs to use the NetBIOS RESET command. For NetBIOS 3.0, the application

must issue a NetBIOS RESET command as the very first command. The RESET

command specifies the resources needed by the application. To accomplish

this, the application should set the following fields in the RESET command

NCB (network control block):

   NCB_CALLNAME[0] (One byte, maximum number of sessions)

   NCB_CALLNAME[1] (One byte, maximum number of NCBs or commands)

   NCB_CALLNAME[2] (One byte, maximum number of names)

The default values for these fields are:

   NCB_CALLNAME[0] 16 (Sessions)

   NCB_CALLNAME[1] 16 (Commands)

   NCB_CALLNAME[2] 8 (Names)

Reference:

"IBM LAN Technical Reference," pages 4-29

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: NtwkNetbios


INF: Supported Versions of Windows Sockets

Article ID: Q101377

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

When using the WSAStartup() Windows Sockets application programming

interface (API)

   int PASCAL WSAStartup ( WORD wVersionRequired, LPWSADATA lpWSAData );

the first parameter specifies the version of Windows Sockets the

application requires.

The 16-bit Windows Sockets dynamic-link library (DLL) for Windows NT

(WINSOCK.DLL) supports versions 1.0 and 1.1.

The 32-bit Windows Sockets DLL for Windows NT (WSOCK32.DLL) supports only

version 1.1. Specifying version 1.0 in the call to WSAStartup() results in

a return of WSAVERNOTSUPPORTED.

The Win32s WSOCK32.DLL thunks down to the 16-bit WINSOCK.DLL, if it is

installed. Win32s 1.1 also requires Windows Sockets 1.1 to provide the

thunks.

Additional reference words: 1.00 1.10 3.10

KBCategory: Prg

KBSubcategory: NtwkWinsock


Location of WNet* API Functions

Article ID: Q102381

--------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

--------------------------------------------------------------

The WNet* API routines are implemented in MPR.DLL. When linking an

application which uses these routines, link with the import library

mpr.lib. For a list of which APIs can be resolved with which import

libraries, see the file win32api.csv, which is included in the Win32 SDK

and the Visual C++ 32-bit edition.

Additional reference words: 3.10

KBCategory: Prg

KBSubCategory: NtwkWinnet


PRB: RPC Installation Problem

Article ID: Q104315

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

There is a problem with the Remote Procedure Call (RPC) service

installation. Setup searches the Windows directory for WINSOCK.DLL. If the

file is found, Setup installs RPC16C3.DLL.

This is a problem if you are dual booting a machine between Windows 3.1 and

Windows NT because Windows 3.1 uses an older TCP/IP interface, which is

called RPC16C3X.DLL on the distribution disks. When you run Windows NT, you

will want to use the newer TCP/IP interface, called RPC16C3.DLL.

WORKAROUND

==========

If you are dual booting and using RPC, a workaround to this problem is to

rename your WINSOCK.DLL file to something else, such as WINSOCK.XXX. This

will cause Setup to copy the correct version of the TCP/IP dynamic-link

library (DLL).

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: NtwkRpc


INF: RpcNsxxx() APIs Not Supported by Windows NT Locator

Article ID: Q104318

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The RpsNSxxx group and profile name service application programming

interfaces (APIs), such as RpcNsProfileEltAdd(), are supported by our RPC

run time; however, they are not supported by the Windows NT Locator, which

is the default RPC name service provider. If you attempt to make a call to

one of these APIs, an error 1764, "request not supported," will be

returned. Because the RpcNSxxx APIs are supported in the run time, name

service providers other than the Locator, such as the DCE CDS, can be

accessed.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: NtwkRpc


INF: Using ReadFile() and WriteFile() on Socket Descriptors

Article ID: Q104536

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

Socket handles for Windows NT sockets are object handles. For example, you

can pass a socket handle in the appropriate state to the ReadFile(),

ReadFileEx(), WriteFile(), or WriteFileEx() application programming

interface (API) to receive and send data. The socket descriptor passed to

the file APIs must be a connected, TCP descriptor.

NOTE: There is no way to specify send and receive out-of-band data.

To use a Windows Sockets handle, the ReadFile() and WriteFile() APIs must

use asynchronous access. That is, you must specify the overlapped parameter

in the call to ReadFile() and WriteFile(). This will allow you to be

notified when the I/O has completed.

This functionality is based upon the implementation of Windows Sockets and

may not be available to all implementations. For instance, although this

works in the Win32 subsystem, it is not supported under Win32s.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: NtwkWinsock


FIX: NDISCloseFile() Does Not Free Image Buffer

Article ID: Q105785

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The NDISCloseFile() function does not free the buffer that it allocates to

hold the image that was read in.

STATUS

======

Microsoft has confirmed this to be a problem in Windows NT and Windows NT

Advanced Server version 3.1. This problem was corrected in the latest U.S.

Service Pack for Windows NT and Windows NT Advanced Server version 3.1. For

information on obtaining the Service Pack, query on the following word in

the Microsoft Knowledge Base (without the spaces):

   S E R V P A C K

Additional reference words: 3.10

KBCategory: Prg

KBSubCategory: NtwkMisc


FIX: APIs Do Incorrect Comparisons

Article ID: Q105804

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The functions getservbyport() and getprotobynumber() do an incorrect

comparison when two port APIs take a parameter as an integer then do

comparisons of the integer against an unsigned short that is incorrectly

sign-extended. If a port or protocol number greater than 127 is passed into

these routines, they will not return any information.

STATUS

======

Microsoft has confirmed this to be a problem in Windows NT and Windows NT

Advanced Server version 3.1. This problem was corrected in the latest U.S.

Service Pack for Windows NT and Windows NT Advanced Server version 3.1. For

information on obtaining the Service Pack, query on the following word in

the Microsoft Knowledge Base (without the spaces):

   S E R V P A C K

Additional reference words: 3.10

KBCategory: Prg

KBSubCategory: NtwkWinsock


INF: Host Name May Map to Multiple IP Addresses

Article ID: Q110703

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The sockets function gethostname() returns a string that identifies the

name of the local host. Each host has only one "official" name,

regardless of how many IP addresses it has, but there may be several

"aliases" for the host.

In TCP/IP, there is not a one-to-one mapping between host name and IP

address. The mapping is one-to-many: one host name can have multiple IP

addresses.

The sockets function getsockname() returns the sockaddr that the socket

is bound to.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: NtwkWinsock


PRB: Winsock select() Returns WSAENOTSOCK

Article ID: Q110775

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The default packing on Microsoft x86 compilers is /Zp8. If you change the

packing on your module by specifying the /Zp option with some other number,

the select() function will return the error WSAENOTSOCK.

CAUSE

=====

The prototype for the select() function is as follows:

   int PASCAL FAR select (int, fd_set FAR *, fd_set FAR *,

      fd_set FAR *, const struct timeval FAR *)

   int nfds;

   fd_set FAR *readfds;

   fd_set FAR *writefds;

   fd_set FAR *exceptfds;

   const struct timeval FAR *timeout;

It is important that the structures of type fd_set be packed with /Zp8.

RESOLUTION

==========

If the structure packing has been changed with the /Zp option on the

compiler command line, put the following

   #pragma pack(8) {

      ...

   }

   #pragma pack()

around the definition of fd_set in the WINSOCK.H header file to eliminate

the WSAENOTSOCK error.

STATUS

======

In the future, the short (the first fd_set structure element) will be

changed to an int to avoid this alignment problem.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: NtwkWinsock


INF: Windows NT Support for the MS-DOS LAN Manager APIs

Article ID: Q110776

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

There is no list that shows specifically which MS-DOS LAN Manager APIs

(application programming interfaces) are supported in a VDM (virtual DOS

machine) on Windows NT. This article discusses what influenced whether or

not an API would be implemented.

The set of APIs that is supported is relatively small. It was necessary to

implement named pipes, mailslots, NetServerEnum(), and the NetUseXXX APIs.

The APIs that are commonly used in shipping applications were implemented,

if possible. There were certain APIs that were impossible to implement from

the VDM. The remaining APIs were not added either because Microsoft did not

feel that they were used in applications or because they did not make sense

in this context, such as the NetServiceXXX APIs.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: NtwkLmapi


INF: Availability of Microsoft Network SDKs

Article ID: Q115604

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1 and 3.5

 - Microsoft Windows SDK, version 3.1

 - Windows for Workgroups SDK, version 3.11

 - Microsoft LAN Manager SDK

----------------------------------------------------------------------

SUMMARY

=======

The following SDKs are available for programmers writing network

applications on Microsoft platforms:

Microsoft Windows for Workgroups SDK

------------------------------------

This is available on the April 1994 (and later) Microsoft Developer Network

(MSDN) Level 2 CDs.

The SDK, documentation, debug kernel, and other files for network

programmers on Windows for Workgroups, version 3.11 are available on the

April 1994 MSDN. This SDK includes APIs for the network extensions to

Windows for Workgroups, version 3.11.

Microsoft LAN Manager SDK

-------------------------

This is available on CompuServe:

   Forum: msnet

   Section: 3 (LM on OS/2)

The libraries in this section contain the SDK.

The SDK for LAN Manager programming on MS-DOS, Windows, and OS/2 is

available on CompuServe.

The documentation is available in two books:

 - "Microsoft LAN Manager, A Programmer's Guide," Ralph Ryan, Microsoft

   Press, ISBN 1-55615-166-7.

 - "Microsoft LAN Manager Programmer's Reference," Microsoft Corporation,

   Microsoft Press, ISBN 1-55615-313-9.

This SDK includes APIs for writing distributed applications and

administration programs for Microsoft LAN Manager.

LAN Manager APIs for Windows NT

-------------------------------

The LAN Manager APIs for Windows NT, version 3.1, are available on the

Win32SDK CD. The file DOC\SDK\MISC\LMAPI.HLP on the CD describes these

APIs. This SDK includes the 32-bit equivalents of most of the previously

mentioned LAN Manager APIs, which are available on Windows NT.

The LAN Manager APIs for Windows NT , version 3.5, are included in the

corresponding SDK. These APIs are described in the Win32 API help file.

Windows Sockets APIs

--------------------

The Windows Sockets APIs for Windows NT, version 3.1 and Windows NT,

version 3.5 are available in the SDKs. The file WINSOCK.HLP gives the

details.

The files needed to support Windows Sockets APIs (conforming to the Windows

Sockets specifications) for Microsoft LAN Manager may be obtained in the

following locations:

 - CompuServe (lib 10 in the MSNETWORKS forum, titled LMSOCK.ZIP).

   -or-

 - Internet (FTP.MICROSOFT.COM, ADVSYS\LANMAN\SUP-ED\WINSOCK).

The Windows Sockets specifications, libraries, header files and samples may

also be obtained from the Internet location mentioned above, in the

ADVSYS\WINSOCK directory.

Microsoft Remote Procedure Call (RPC)

-------------------------------------

The support for RPC is included in the Windows NT, version 3.1 and Windows

NT, version 3.5 SDKs. The Win32 API help file for Windows NT, version 3.1,

includes the RPC APIs. The RPC.HLP file in the Windows NT, version 3.5 SDK

gives the details of RPC support.

RPC support files for MS-DOS and Microsoft Windows may be obtained from the

Win32SDK CD-ROM. The directory MSTOOLS\RPC_DOS has the required files.

NOTE: Microsoft also provides other kinds of network APIs. For example, the

NetBIOSCall() API provides a mechanism to write NetBIOS applications on

Microsoft Windows; on Windows NT this is accomplished with the Netbios()

API. Information on these other APIs may be obtained from the Windows and

Windows NT SDK documentation.

Additional reference words: 3.10 3.50 3.11

KBCategory: Ref

KBSubCategory: NtwkMisc


INF: MIDL 1.0 and MIDL 2.0 Full Pointers Do Not Interoperate

Article ID: Q115830

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.5

----------------------------------------------------------------------

Microsoft Remote Procedure Call (RPC), version 1.0, has minimal support for

full pointers, so the version of the MIDL compiler with Microsoft RPC

version 1.0 (MIDL 1.0) treats full pointers (specified with the ptr

attribute) as unique pointers (specified with the unique attribute).

The MIDL compiler with Microsoft RPC, version 2.0 (MIDL 2.0), supports full

pointers. Because of the way Microsoft RPC, version 1.0, handles the on-

wire representation of pointers, applications compiled using MIDL 2.0 full

pointers cannot operate interactively with applications compiled using MIDL

1.0 full pointers.

The workaround is to recompile the MIDL 2.0 application to use unique

pointers.

Additional reference words: 3.50

KBCategory: Prg

KBSubcategory: NtwkRpc


INF: Global Classes in Win32

Article ID: Q80382

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Under Windows, when an application wants to check whether or not a window

class has been previously registered in the system, it typically checks

hPrevInstance. Under Windows NT, hPreviousInstance is always FALSE, because

a class definition is not available outside the process context of the

process that registers it. Thus, code that checks hPreviousInstance will

always register the window class.

MORE INFORMATION

================

Under Windows NT, a style of CS_GLOBALCLASS indicates that the class is

available to every DLL in the process, not every application and DLL in the

system, as it does in Windows 3.1.

In order to have a class registered for every process in the system under

Windows NT, it is necessary to

1) register the class in a DLL

2) use a style of CS_GLOBALCLASS

3) list the DLL in the following registry key

   HKEY_LOCAL_MACHINE\S OFTWARE\

      Microsoft\

      Windows NT\

      CurrentVersion\

      Windows\

      AppInit_DLLs

   This will force the DLL to be loaded into every process in the system,

   thereby registering the class in each and every process.

For more information, please see "Window Classes in Win32", which is

available on the MSDN CD, starting April '94.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrCls


INF: Unicode Conversion to Integers

Article ID: Q89295

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Under Windows NT, strings may be either Unicode or ANSI. There is no

function for reliably converting a string that might be either Unicode or

ANSI to an integer. This is because, given a random set of bytes, it is

difficult to determine whether the string is in Unicode or ANSI. The

calling program has to know which format the string uses in order to

convert it.

If the string uses Unicode, the functions wcstol(), wcstoul(), and wcstod()

can be used to perform the conversion.

Note that when you are using the Win32 application programming interface

(API), you can choose what kind of characters you get from the console or

window manager. The names of the API functions that are called to use

Unicode and ANSI characters are different. For more details, see Chapter 93

in the overview, "Unicode."

To mark a string as Unicode, insert the byte-ordering-mark (BOM) 0xFEFF in

the string and/or file.

MORE INFORMATION

================

You can assume that the first 128 bytes in each character set are in the

same codepoint. For portability, you should code character conversions in

this range as:

   {

      TCHAR     c;

        ...

        i = c - TEXT('0');

   }

The TEXT macro places an "L" before the constant if Unicode is defined.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrNls


INF: Multiline Edit Control Limits in Windows NT

Article ID: Q89712

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The default maximum size for a multiline edit (MLE) control in both Windows

and Windows NT is 30,000 characters. The EM_LIMITTEXT message allows an

application to increase this value. Setting "cchmax" to 0 is a portable

method of increasing this limit to the maximum in both Windows and Windows

NT. When cchmax is set to 0, the maximum size for an MLE is 4GB-1 (4

gigabytes minus 1).

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrCtl


INF: Tips for Writing Multiple-Language Scripts

Article ID: Q89865

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

To aid you in writing multiple-language resources, the Win32 development

system supports language scripts.

MORE INFORMATION

================

To create a multiple language script, first create a single-language script

file (American English, for example), and duplicate the translations in

your script file. You need a complete translation only once for each major

language. Only those resources that have differences between the major

language and the sublanguage need be included in the sublanguage areas of

the script. The system will use the main language resource if it doesn't

find a resource for the sublanguage.

Sample Code

-----------

LANGUAGE LANG_ENGLISH,SUBLANG_ENGLISH_US

<original script file>

LANGUAGE LANG_ENGLISH,SUBLANG_ENGLISH_UK

<portions of script file that are different for UK>

LANGUAGE LANG_ENGLISH,SUBLANG_ENGLISH_AUS

<portions of script file that are different for Australia>

LANGUAGE LANG_ENGLISH,SUBLANG_ENGLISH_CAN

<portions of script file that are different for Canada>

LANGUAGE LANG_FRENCH,SUBLANG_FRENCH

<entire script file translated to French>

LANGUAGE LANG_FRENCH,SUBLANG_FRENCH_CAN

<portions of script file that are different for Canada>

LANGUAGE LANG_FRENCH,SUBLANG_FRENCH_SWISS

<portions of script file that are different for Switzerland>

LANGUAGE LANG_FRENCH,SUBLANG_FRENCH_BELGIAN

<portions of script file that are different for Belgium>

LANGUAGE LANG_SPANISH,SUBLANG_SPANISH

<entire script file translated to Spanish>

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrNls


INF: Writing Multiple-Language Resources

Article ID: Q89866

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

When you are writing multiple-language resources, the dialog box

identifiers need to be identical for each language instance, as

demonstrated below.

   #define DialogID       100

   DialogID DIALOG  0, 0, 210, 10

   LANGUAGE LANG_ENGLISH,SUBLANG_ENGLISH_US

   .

   .

   .

   DialogID DIALOG  0, 0, 210, 10

   LANGUAGE LANG_FRENCH,SUBLANG_FRENCH

The FindResource() application programming interface (API) function is used

by the system to fetch the dialog box. FindResource() gets the locale

information for the process, then attempts to fetch the resource with that

language identifier using FindResourceEx(), the language-specific API

function for fetching resources. If FindResourceEx() fails to load the

language-specific dialog box, FindResource() then attempts to load the

neutral dialog box, which should fetch LANG_FRENCH,SUBLANG_FRENCH, if the

locale is SUBLANG_FRENCH_CAN or similar.

The LANGUAGE identifiers and the VERSIONINFO language identifiers should

also be identical. The code page for resources is always the Unicode code

page. The system will translate from Unicode to the required code page.

The preferred method of developing multiple-language resources is to

include a LANGUAGE statement for each language supported rather than using

the CODEPAGE, LANGUAGE identifier, and VERSIONINFO information. Although

the CODEPAGE information will work, the new method is easier to use.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrNls


INF: Getting the WinMain() lpCmdLine in Unicode

Article ID: Q90912

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The prototype for WinMain() is as follows:

   int PASCAL WinMain(

          HANDLE hInstance,

          HANDLE hPrevInstance,

          LPSTR lpCmdLine,

          int nCmdShow );

The third parameter is an LPSTR, which specifies an ANSI string. WinMain()

cannot be defined to accept Unicode input because there is no way for the

system to know whether or not the application wants Unicode at the time

WinMain() is called; the system knows once the application has registered a

window class.

To get the arguments in Unicode, use GetCommandLine().

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrNls


INF: Creating Windows in a Multithreaded Application

Article ID: Q90975

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

In a multithreaded application, any thread can call the CreateWindow() API

to create a window. There are no restrictions on which thread(s) can create

windows.

It is important to note that the message loop and window procedure for the

window must be in the thread that created the window. If a different thread

creates the window, the window won't get messages from DispatchMessage(),

but will get messages from other sources. Therefore, the window will appear

but won't show activation or repaint, cannot be moved, won't receive mouse

messages, and so on.

MORE INFORMATION

================

Normally, windows created in different threads process input independently

of each other. The windows have their own input states and the threads are

not synchronized with eachother in regards to input processing.

In order to have threads to share input state, have one thread call

AttachThreadInput() to have its input processing attached to another

thread. What this means is that these two threads will use a Windows 3.1

style system queue. The threads will still have separate input, but they

will take turns reading out of the same queue.

Creating a window can force an implicit AttachThreadInput(), when a parent

window is created in one thread and the child window is being created in

another thread. When windows are created (or set) in separate threads with

a parent-child relationship, the input queues are attached.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrWndw


INF: Multiple Desktops Under Windows NT

Article ID: Q92505

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Windows NT does not support sharing the same desktop between two monitors

on the same machine. An independent software vendor (ISV) that wants this

capability must write a display device driver that behaves similar to a

normal driver with a single monitor, but actually controls two monitors.

Additional reference words: 3.10

KBCategory:

KBSubcategory: UsrMisc


INF: DDEML Application-Instance IDs Are Thread Local

Article ID: Q94091

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

When using the DDEML (Dynamic Data Exchange Management Library) libraries

from a spawned thread, the application-instance ID that is returned in the

lpidInst parameter of DdeInitialize is thread local.

Therefore, the application-instance ID cannot be used by any other thread

that is spawned by the process, nor can it be inherited from the parent.

To use the DDEML libraries within a thread, it is necessary to make both

the DdeInitialize call and to use the DdeUninitialize call from within the

thread; otherwise, there is no way to terminate the DDEML session.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrDde


INF: Freeing PackDDElParam() Memory

Article ID: Q94149

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

When posting DDE messages via PostMessage(), an application first calls

PackDDElParam() and sends its return value (a pointer cast to LPARAM) as

the lParam in PostMessage().

Normally the receiving application is responsible for freeing the structure

[via FreeDDElParam()]. However, if the call to PostMessage() fails, the

posting application must free the packed data. This is also the method used

by 16-bit Windows.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrDde


INF: Uniqueness Values in User and GDI Handles

Article ID: Q94917

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

User and GDI handles, are divided into two parts:

 - The lower 16 bits is an index into a system table of handle

   structures, which includes information such as the type of handle

   (window, menu, cursor, and so forth), as well as a value called the

   uniqueness.

 - The upper 16 bits contain the same uniqueness value.

The first time a handle is issued by the system, the uniqueness value is 0

(zero). It is incremented each time the handle is re-used. If you pass in a

value of 0xFFFF for the uniqueness, the client side (that is, USER32.DLL)

will look up the correct uniqueness value in shared memory and use the

correct handle.

This is important because it alleviates potential conflicts with re-used

handles. For instance, when a window is destroyed, its handle is reused by

the system. The uniqueness value prevents an old handle to a destroyed

window from being misinterpreted by the system as the handle to a new

object, which was given the same handle value.

MORE INFORMATION

================

In Win32s, use 0x0000 in the upper 16 bits for the uniqueness.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrMisc


INF: SendMessage() in a Multithreaded Environment

Article ID: Q95000

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

When thread X calls SendMessage() to send a message to a window created by

thread Y, it must wait until thread Y calls PeekMessage(), GetMessage(), or

WaitMessage() before the SendMessage() call can continue. This process

prevents synchronization problems.

MORE INFORMATION

================

Because of the multithreaded environment of Windows NT, SendMessage() does

not behave in the same manner as it does under Windows 3.1. Under Windows

3.1, SendMessage() simply calls the window procedure given to it. In

Windows 3.1, if you use the SendMessage() function to send a message to a

window of another task, the system will perform a task switch to the target

window (change to the stack of the target Windows application), let the

target window process the message [when it calls GetMessage() or

PeekMessage()], and then switch back to the original message.

Under Windows NT, however, only the thread that created a window may

process the window's messages. Therefore, if thread X sends a message [via

SendMessage()] to a window that was created by thread Y, thread X must wait

for thread Y to be in a receiving state, and handle the message for it.

Thread Y is only in a receiving state when it calls PeekMessage(),

GetMessage(), or WaitMessage(), because synchronization problems may occur

if a thread is interrupted while processing other messages. While in a

receiving state, thread Y may process messages sent to its windows via

SendMessage() (in this case, by thread X).

Note that PeekMessage() and GetMessage() look in thread Y's message queue

for messages. Because SendMessage() does not post any messages,

PeekMessage() and GetMessage() will not see any indication of the

SendMessage() call. The two functions merely serve as a point in time at

which SendMessage() (thread X) may "interrupt," and have thread Y process

its message next. Then PeekMessage() or GetMessage() continues normal

operation under thread Y.

Because of this behavior, if thread X sends a message to thread Y, and

thread Y is locked in a tight loop, thread X is now locked as well. This

may be prevented by using SendNotifyMessage(), which behaves as

SendMessage() does above, but returns immediately. This may be an advantage

if it is not important that the sent message be completed before thread Y

continues. Note, however, that because SendNotifyMessage() is asynchronous,

thread X should not pass pointers to any of its local variables when making

the call, because they may be gone by the time thread Y attempts to look at

them. This would result in a general protection violation (GP fault) when

thread Y accesses the pointer.

Additional reference words: 3.10 GP-fault

KBCategory: Prg

KBSubcategory: UsrMisc


INF: Window Message Priorities

Article ID: Q96006

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Under Windows NT, messages have the same priorities as with Windows 3.1.

With normal use of GetMessage() (passing zeros for all arguments except the

LPMSG parameter) or PeekMessage(), any message on the application queue is

processed before user input messages. And input messages are processed

before WM_TIMER and WM_PAINT "messages."

MORE INFORMATION

================

For example, PostMessage() puts a message in the application queue.

However, when the user moves the mouse or presses a key, these messages are

placed on another queue (the system queue in Windows 3.1; a private, per-

thread input queue in Win32).

GetMessage() and its siblings do not look at the user input queue until the

application queue is empty. Also, the WM_TIMER and WM_PAINT messages are

not handled until there are no other messages (for the thread) to process.

The WM_TIMER and WM_PAINT messages can be thought of as boolean toggles,

because multiple WM_PAINT or WM_TIMER messages waiting in the queue will be

combined into one message. This reduces the number of times a window must

repaint itself.

Under this scheme, prioritization can be considered tri-level. All posted

messages are higher priority than user input messages because they reside

in different queues. And all user input messages are higher priority than

WM_PAINT and WM_TIMER messages.

The only difference in the Windows NT model from the Windows versions 3.x

model is that there is effectively a system queue per thread (for user

input messages) rather than one global system queue. The prioritization

scheme for messages is identical.

For information concerning SendMessage() from one thread to another, please

see the following article(s) in the Microsoft Knowledge Base:

   ARTICLE-ID: Q95000

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrWndw


INF: NULL is a Valid Return From SetWindowsHook()

Article ID: Q97920

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

NULL may be returned as a valid handle from a call to SetWindowsHook().

NULL will be returned when installing the first hook of a particular hook

type (with the exception of the WH_KEYBOARD and WH_MESSAGE hook types).

This behavior is compatible with Windows version 3.0.

The SetWindowsHook() API returns NULL when you try to set a WH_MSGFILTER,

WH_MOUSE, or WH_DEBUG hook. GetLastError() returns 0x57 "invalid

parameter". However, the hook procedure does get called normally and the

hook is successfully set.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrHks


INF: LB_GETCARETINDEX Returns 0 for Zero Entries in List Box

Article ID: Q97922

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

To determine whether a multiple selection list box is empty or has no items

to select, two messages are required. First, call LB_GETCOUNT to determine

whether or not the list box is empty. If the list box is not empty, then

use LB_GETCARETINDEX to determine the position of the caret.

If you want a list box to contain selections that remain after the focus

goes elsewhere, Microsoft recommends using visible check marks next to the

items in the list box. This method provides better visual feedback to the

user than a selection bar.

Additional reference words: 3.10 listbox

KBCategory: Prg

KBSubcategory: UsrCtl


INF: SetActiveWindow() and SetForegroundWindow() Clarification

Article ID: Q97925

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

By default, each thread has an independent input state (its own active

window, its own focus window, and so forth). SetActiveWindow() always

logically sets a thread's active window state. To force a window to the

foreground, however, use SetForegroundWindow(). SetForegroundWindow()

activates a window and forces the window into the foreground.

SetActiveWindow() always activates, but it brings the active window into

the foreground only if the thread is the foreground thread.

NOTE: If the target window was not created by the calling thread, the

active window status of the calling thread is set to NULL, and the active

window status of the thread that created the target window is set to the

target window.

Applications can call AttachThreadInput() to allow a set of threads to

share the same input state. By sharing input state, the threads share their

concept of the active window. By doing this, one thread can always activate

another thread's window. This function is also useful for sharing focus

state, mouse capture state, keyboard state, and window Z-order state among

windows created by different threads whose input state is shared.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrWndw


INF: UNICODE and _UNICODE Needed to Compile for Unicode

Article ID: Q99359

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

To compile code for Unicode, you need to #define UNICODE for the Win32

header files and #define _UNICODE for the C Run-time header files. These

#defines must appear before the

   #include <windows.h>

and any included C Run-time headers. The leading underscore indicates

deviance from the ANSI C standard. Because the Windows header files are not

part of this standard, it is allowable to use UNICODE without the leading

underscore.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrNls


INF: Memory Handles and Icons

Article ID: Q99360

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Memory handles are not globally sharable among processes. Handles for

icons, cursors, windows, and so forth, are not global handles but are

handles into an index into the server-side handle table (the handle is

actually an index into the server-side's handle table). Thus, some objects

can be shared between processes -- but probably shouldn't be, for

concurrency reasons.

GDI-related objects, however, are stored in a client-side handle table,

which is translated to a handle value in a server-side table on every

client-server transition. Thus, there are some objects that can be shared

(USER-related objects) and some that can't be shared (BASE/KERNEL and GDI).

MORE INFORMATION

================

There are three types of handles in the system:

 - Handles to objects that the executive (object manager) knows

   about. These are assigned on a per-process basis but each access to

   these objects goes through the executive.

 - Handles that are maintained by the Win32 subsystem server (USER

   objects, including icons and cursors) and are therefore sharable.

   Please note that the allowed behavior of shared USER objects is

   subject to change in future releases of Windows NT. Thus, care

   should be taken when using these handles.

 - Handles that are maintained by the Win32 subsystem client, and

   therefore are valid only in the context of the process that created

   it (GDI objects). These handles differ from the first type of

   handles listed in that you cannot call handle manipulation

   functions, such as DuplicateHandle() an WaitForSingleObject(), or

   use the security facilities on these objects.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrMisc


INF: Using SetThreadLocale() for Language Resources

Article ID: Q99392

---------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

---------------------------------------------------------------------

Under Windows NT, each resource loading application programming interface

(API) is based on the thread's locale. Each thread has a locale--usually

the default system locale.

You can change the thread locale by calling SetThreadLocale(). To obtain

the language resource you want, just set the thread locale to the locale

you want, then call the normal resource loading API.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrNls


PRB: AttachThreadInput() Resets Keyboard State

Article ID: Q100486

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

Start with a program that calls AttachThreadInput() to a thread in another

process. Call GetKeyboardState() to get the current key. Call

SetKeyboardState() to set the keystate. This call returns TRUE, indicating

success, but the keystate is not successfully set.

If the thread is in the same process, calling SetKeyboardState() works as

expected.

CAUSE

=====

When attaching to another thread, a temporary message queue is created.

This queue contains a copy of the keystate information from the queue to

which you are attaching. When the keystate is set, the temporary queue

keystate is updated and the application programming interface (API)

succeeds. However, when the detach occurs, the keystate change information

is lost and reverts to what it was before the attach.

RESOLUTION

==========

To work around the problem, either:

 - Stay attached

   -or-

 - Use hooks

STATUS

======

This problem will not be resolved in the release of Windows NT version 3.1;

however, a resolution is being considered for a future release.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrMisc


INF: System Versus User Locale Identifiers

Article ID: Q100488

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

In Windows NT version 3.1, the following pairs of application programming

interfaces (APIs) have the same functionality:

   GetSystemDefaultLCID()   and GetUserDefaultLCID()

   GetSystemDefaultLangID() and GetUserDefaultLangID()

The user LangID and LCID are always set to the system value. In future

versions of Windows NT, it will be possible to set the LangID and the LCID

on a per-user basis.

Note that it is possible to set the LCID on a per-thread basis [that is,

SetThreadLocale()] in Windows NT 3.1.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrLoc


PRB: Unicode ChooseColor() Help Button May Crash Common Dialog

Article ID: Q102026

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

A Unicode compiled program, or a program that explicitly calls the

ChooseColorW() function, may suffer an access violation in the common

dialog boxes if the Help button in the ChooseColor() dialog box is chosen.

CAUSE

=====

This problem may not be 100-percent reproducible. Because of the way that

the program loader loads code into memory, a certain address referenced by

the common dialog box Help button logic may or may not be valid depending

on what other applications have been run, what application is calling

ChooseColorW(), and the order in which these programs are run.

WORKAROUND

==========

The following are suggested workarounds:

 - Try running an ANSI-compiled application that uses the common

   dialog boxes, and open one of the common dialog boxes before you run

   the application having this problem.

 - A workaround for new applications developers is to call

   ChooseColorW() with a hook function (see the Windows Software

   Development Kit documentation for more information on common dialog

   box hook functions), handle the Help button logic, and return TRUE

   from the hook function to bypass the standard common dialog box

   push-button code.

Additional reference words: 3.10

KBCategory: Prg

KBSubCategory: UsrCmnDlg


INF: Debugging a System-Wide Hook

Article ID: Q102428

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Debugging a system-wide hook such as a journal hook must be done with the

extreme caution. When an application installs such a hook, it effectively

takes control of user input. In effect, this disables the interface with

the debugger. For example, after installing a journal record hook, you must

unhook the record hook when you want to allow the debugger to regain

control.

It is not possible to use an interactive debugger to debug an actively

installed journal hook using a single machine. It is possible to use a

remote debugger, because one interface can be blocked (or recording) while

the other one does the debugging.

MORE INFORMATION

================

System-wide input hook procedures can be thought of as being in three

possible states:

   unhooked (not installed)

   suspended

   hooked (installed)

In the unhooked state, the procedure imposes no control over user input. In

the hooked state, all user input specifically defined to be handled by this

hook passes through this procedure. In the suspended state, all user input

specifically defined to be handled by this hook is completely blocked.

In the case of a journal record hook, the suspended state can be achieved

when a breakpoint is reached within the hook procedure. When this happens,

all user input (system wide, that is) in the form of mouse and keyboard

input is blocked, and thus you cannot interact with the debugger or any

other application as you normally would. Fortunately, when the user presses

the CTRL+ESC or the CTRL+ALT+DEL key combinations, all system-wide hooks

are automatically unhooked, returning the system to the unhooked state.

Once this has occurred, it is likely that the application with the journal

hook is now in a undefined state (because it had the hook pulled out from

underneath it, so to speak). Fortunately, the system will send all

applications the WM_CANCELJOURNAL message to indicate that it has removed

the hook. A well behaved application can intercept this message and adjust

its state accordingly.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrHks


DOCERR: WM_ENTERIDLE Documentation Is Misleading

Article ID: Q102446

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The Win32 application programming interface (API) online documentation

for the WM_ENTERIDLE message states the following:

   The WM_ENTERIDLE message informs an application's main window

   procedure that a modal dialog box or menu is entering an idle

   state.

This is incorrect for dialog boxes. The WM_ENTERIDLE message is sent to the

dialog box's owner window rather than the application's main window as the

documentation states.

RESOLUTION

==========

A modal dialog box or menu enters an idle state when no messages are

waiting in its queue after it has processed one or more previous messages.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrMisc


INF: SetTimer() Should Not Be Used in Console Applications

Article ID: Q102482

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

SetTimer() was not designed to be used with a console application because

it requires a message loop to dispatch the timer signal to the timer

procedure. In a console application, this behavior can be easily emulated

with a thread that is set to wait on an event.

MORE INFORMATION

================

SetTimer() can work within a console application, but it requires a thread

in a loop calling GetMessage() and DispatchMessage().

For example,

   while (1)

   {

      GetMessage();

      DispatchMessage();

   }

Because this requires a thread looping, there is no real advantage to

adding a timer to a console application over using a thread waiting on an

event.

Another option is to use a multimedia timer, which does not require a

message loop and has a higher resolution. See the help for timeSetEvent()

and the Multimedia overview. Any application using Multimedia calls must

include MMSYSTEM.H, and must link with WINMM.LIB.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrMisc


INF: The SBS_SIZEBOX Style

Article ID: Q102485

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

A size box is a small rectangle the user can expand to change the size of

the window. When you want a size box, you create a SCROLLBAR window with

the SBS_SIZEBOX flag. This action creates a size box with the height,

width, and position that you specified in the call to CreateWindow. If you

specify SBS_SIZEBOXBOTTOMRIGHTALIGN, the box will be aligned in the lower

right of the rectangle you specified when creating the window. If you

specify SBS_SIZEBOXTOPLEFTALIGN, the box will be aligned in the upper left

of the rectangle you specified in your call to CreateWindow().

MORE INFORMATION

================

The user moves the mouse pointer over to the box, presses and holds the

left mouse button, and drags the mouse pointer to resize the window. When

the user does this, the borders on the window (the frame) move. When the

user releases the mouse button, the window is resized.

You create a size box by creating a child window of type WS_CHILD |

WS_VISIBLE | SBS_SIZEBOX | SBS_SIZEBOXTOPLEFTALIGN. You don't have to do

any of the processing for this; the system will take care of it. You will

notice in your window procedure that you will get the scroll bar messages

plus the WM_MINMAXINFO message. Size boxes work similar to the way the

WS_THICKFRAME/WS_SIZEBOX style does on a window.

Additional reference words: sizebox

KBCategory: Prg

KBSubcategory: UsrCtl


INF: Clarification of the "Country" Setting

Article ID: Q102765

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Under Windows NT, the "Country" choice affects currency, date/time and

number format, and so forth. The "Language" choice affects sorting, names

of the days of the weeks and months, and so forth. These settings allow the

user to choose the appropriate language and country format. For example, if

you are British and living in the U.S., you can pick a locale of English

(British) at setup time, then use Control Panel later to change your

country to U.S. so that currency is in dollars instead of pounds.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrNls


PRB: CloseClipboard() Suggests Calling DuplicateHandle()

Article ID: Q103240

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The documentation for CloseClipboard() suggests using DuplicateHandle() on

a clipboard object before closing the clipboard, in order to use that

object after the clipboard is closed. Doing so results in a return of

ERROR_INVALID_HANDLE.

STATUS

======

The documentation is in error. DuplicateHandle() is specified to work only

on console input, console output, events, files, file mappings, mutexes,

pipes, processes, semaphores, and thread handles.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrClp


INF: Differences Between hInstance on Win 3.1 and Windows NT

Article ID: Q103644

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

In Microsoft Windows version 3.1, an instance handle can be used to

uniquely identify the instance of an application because instance handles

are unique within the scope of an address space. Because each instance of

an application runs in its own address space on Windows NT, instance

handles cannot be used to uniquely identify an instance of an application

running on the system. This article explains why, and some alternative

calls that might assist in uniquely identifying an application instance on

Windows NT.

MORE INFORMATION

================

Although the concepts for an instance handle are similar on Windows NT and

Windows 3.1, the results you see regarding them might be very different

from what you expect.

With Windows 3.1, when you start several instances of the same application,

they all share the same address space. You have multiple instances of the

same code segment; however, each of these instances has a unique data

segment associated with it. Using an instance handle (hInstance) is a way

to uniquely identify these different instances and data segments in the

address space.

Instance handles are unique to the address space. On Windows NT, when

looking at the value of the instance handle, or the value returned from

GetWindowLong(hWnd, GWL_HINSTANCE), a developer coming from a Windows 3.1

background might be surprised to see that most of the windows on the

desktop return the same value. This is because the return value is the

hInstance for the instance of the application, which is running it its own

address space. (An interesting side note: The hInstance value is the base

address where the application's module was able to load; either the default

address or the fixed up address.)

On Windows NT, running several instances of the same application causes the

instances to start and run in their own separate address space. To

emphasize the difference: multiple instances of the same application on

Windows 3.1 run in the same address space; in Windows NT, each instance has

its own, separate address space. Using an instance handle to uniquely

identify an application instance, as is possible on Windows 3.1, does not

apply in Windows NT. (Another interesting side note: Remember that even if

there are multiple instances of an application, if they are able to load at

their default virtual address spaces, the virtual address pages of the

different applications' executable code will map to the same physical

memory pages.)

In Windows NT, instance handles are not unique in the global scope of the

system; however, window handles, thread IDs, and process IDs are. Here are

some calls that may assist in alternative methods to uniquely identify

instance of applications on Windows NT:

 - GetWindowThreadProcessID() retrieves the identifier of the thread

   that created the given window and, optionally, the identifier of

   the process that created the window.

 - OpenProcess() returns a handle to a process specified by a process

   ID.

 - GetCurrentProcessID() returns the calling process's ID.

 - EnumThreadWindows() returns all of the windows associated with a

   thread.

 - The FindWindow() function retrieves the handle of the top-level

   window specified by class name and window name.

 - To enumerate all of the processes on the system, you can query the

   Registry using RegQueryValueEx() with key HKEY_PERFORMANCE_DATA,

   and the Registry database index associated with the database string

   "Process".

For further details on using these calls, please see the Win32 SDK help

file.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrMisc


INF: Unicode Implementation in Windows NT 3.1

Article ID: Q103977

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Windows NT is the first widely available operating system to be built

upon the Unicode character encoding. Almost all of the strings used in

the system have 16-bits reserved for each character. However, Windows

NT does not yet realize the Unicode ideal of offering an editor

capable of handling one document containing all of the languages of

the world.

MORE INFORMATION

================

Unicode support in Windows NT:

 - All Windows USER objects support Unicode strings.

 - The Win32 console is Unicode enabled.

 - NTFS supports Unicode filenames.

 - All of the information strings in the registry are Unicode.

 - The L_10646.TTF font covers over 1300 Unicode characters.

 - Most of the TrueType fonts include a Unicode encoding table.

Unicode features missing from Windows NT:

 - There is not font support for all of the Unicode characters.

 - Although the Win32 console is Unicode enabled, it is not possible to

   use Unicode fonts in the console. Most Unicode characters will be

   represented by the "default character" of the System font.

 - Winhlp32 is not Unicode enabled.

 - There is no general Unicode input method. (In fact, it is still not

   clear how this problem is gracefully solved.)

 - The FAT and HPFS file systems do not support Unicode filenames.

   (Nor will they in the future; to accomplish this, use NTFS.)

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrNls


INF: Unicode Font UCLUCIDA.TTF Renamed to L_10646.TTF

Article ID: Q103978

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

During the beta program for Windows NT, the operating system was

distributed with a Unicode font that supports over 1300 different

glyphs. This font was named UCLUCIDA.TTF during the beta program.

However, for the final release of Windows NT, the font has been

renamed to L_10646.TTF. The two files are essentially identical except

for the filenames. The font facename is the same for both files; it is

"Lucida Sans Unicode."

The L_10646.TTF font is not installed by default. Use the Control

Panel, Fonts utility to install it. To see all of the glyphs present

in Lucida Sans Unicode, use the Ttfonts sample application. Ttfonts is

distributed with the Win32 Software Development Kit and VC++ for

Windows NT.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrNls


INF: Propagating Environment Variables to the System

Article ID: Q104011

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

User environment variables can be modified using the System control panel

application or by editing the following Registry key:

   HKEY_CURRENT_USER \

         Environment

System environment variables can be modified by editing the following

Registry key:

   HKEY_LOCAL_MACHINE \

               SYSTEM \

    CurrentControlSet \

              Control \

      Session Manager \

          Environment

Note, however, that modifications to the environment variables do not

result in immediate change. For example, if you start another Command

Prompt after making the changes, the environment variables will reflect the

previous (not the current) values. The changes do not take effect until you

log off and then log back on.

To effect these changes without having to log off, broadcast a

WM_WININICHANGE message to all windows in the system, so that any

interested applications (such as Program Manager, Task Manager, Control

Panel, and so forth) can perform an update.

MORE INFORMATION

================

For example, the following code fragment should propagate the changes to

the environment variables used in the Command Prompt:

   SendMessage( FindWindow( "Progman", NULL ), WM_WININICHANGE,

     0L, (LPARAM) "Environment" );

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrMisc


INF: Mapping .INI File Entries to the Registry

Article ID: Q104136

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

Under Windows NT, .INI file variables are mapped into the Registry as

defined in the

   HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\IniFile

mapping key. The Win32 Profile application programming interface (API)

functions look for a mapping by looking up the filename extension portion

of the profile file. If a match is found, then the search continues under

that node for the specified application name. If a match is found, then the

search continues for the variable name. If the variable name is not found,

the value of the (NULL) variable name is a string that points to a node in

the Registry, whose value keys are the variable names. If a specific

mapping is found for the variable name, then its value points to the

Registry value that contains the variable value.

The Profile API calls go to the Windows server to look for an actual .INI

file, and read and write its contents, only if no mapping for either the

application name or filename is found. If there is a mapping for the

filename but not the application name, and there is a (NULL) application

name, the value of the (NULL) variable will be used as the location in the

Registry of the variable, after appending the application name to it.

In the string that points to a Registry node, there are several

prefixes that change the behavior of the .INI file mapping:

   ! - This character forces all writes to go both to the Registry and

       to the .INI file on disk.

   # - This character causes the Registry value to be set to the value

       in the Windows 3.1 .INI file when a new user logs in for the

       first time after setup.

   @ - This character prevents any reads from going to the .INI file

       on disk if the requested data is not found in the Registry.

   USR: - This prefix stands for HKEY_CURRENT_USER, and the text after

          the prefix is relative to that key.

   SYS: - This prefix stands for HKEY_LOCAL_MACHINE\Software, and the

          text after the prefix is relative to that key.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseMisc


INF: 32-Bit Scroll Ranges

Article ID: Q104311

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

You can use 32-bit scroll ranges by calling GetScrollPos(); however, you

cannot get 32-bit positions for notifications sent while thumb tracking,

that is, via the SB_THUMBPOSITION message. This is because thumb position

information is not queryable via an application programming interface

(API). You only can obtain the 32-bit scroll information only before or

after the scroll has taken place.

The scroll bar APIs allow setting a scroll range up to 0x7FFFFFFF via

SetScrollRange(), and setting a scroll position within that range using

SetScrollPos(). If the WM_HSCROLL or WM_VSCROLL message is processed, the

information returned for scroll bar position, nPos, is only a 16-bit value.

To obtain the 32-bit information, the GetScrollPos() API must be used.

Additional reference words: 3.10 scrollbar

KBCategory: Prg

KBSubcategory: UsrCtl


INF: How Keyboard Data Gets Translated

Article ID: Q104316

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Keyboard input is acquired by the keyboard driver, which in turn produces a

scan code. This scan code is passed on to the locale-specific Win32

subsystem keyboard driver. This locale-specific driver then converts the

scan code to a virtual key and a Unicode character. The Win32 subsystem

then passes on this information to the application.

All messages in the Win32 application programming interface (API) that

present textual information to a window procedure depend upon how the

window registered its class. For instance, if RegisterClassW() was called,

then Unicode is presented; if RegisterClassA() was called, then ANSI is

presented. The conversion of the text is handled by the Window Manager.

This allows an ANSI application to send textual information to a Unicode

application.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrInp


INF: COMCTL32 APIs Unsupported in the Win32 SDK

Article ID: Q105300

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The library COMCTL32.LIB was included in the Win32 SDK because the PERFMON

sample makes use of it. The library is part of the Windows for Workgroups

(WFW) COMMCTRL.LIB. However, Microsoft does not officially support

COMCTL32.LIB or recommend the use of these application programming

interfaces (APIs), and therefore they have not been documented in the SDK.

Microsoft does not recommend these APIs because most of the interfaces will

change in future versions of Windows and Windows NT. Therefore, Microsoft

will not be supporting COMCTL32.

If you must absolutely use COMCTL32 at this time, the documentation can be

found in the WFW SDK. Be aware that the code that you write will break in

future operating systems.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrCtl


INF: Win32 Shell Dynamic Data Exchange (DDE) Interface

Article ID: Q105446

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Information on the DDE Interface to Program Manager can be found in the

Win32 application programming interface (API) reference under the topic

"Shell Dynamic Data Exchange Interface."

The SDK contains a sample program that interfaces with Program

Manager. The sample can be found in MSTOOLS\SAMPLES\DDEML\DDEPROG.

MORE INFORMATION

================

AppProperties cannot be used to get the item icon, description, or

working directory, as it can in Windows 3.1. Therefore, GetIcon(),

GetDescription(), and GetWorkingDir() do not work in Windows NT.

However, AppProperties can still be used to dump out the contents of a

group, by specifying the group name in lParam.

Here's how a Win32 application can get the item icon, the description,

and the working directory:

1. Initiate a conversation with the Shell as follows

      SendMessage( -1, WM_DDE_INITIATE, hWndApp, lParam );

   where lParam points to an atom representing:

      LOWORD | HIWORD

      -----------------------------------------------------------

      Shell  | AppIcon        : To get an item's icon

      Shell  | AppDescription : To get an item's description

      Shell  | AppWorkingDir  : To get an item's working directory

2. Get the item DDE number.

   The DDE number is stored by Program Manager in the STARUPINFO

   structure of the application when the application is started. The

   application can get the startup information with:

      GetStartupInfo( &StartupInfo );

   The field lpReserved in the STARUPINFO structure is in the

   following format

      dde.#, hotkey.##

   where the DDE number is # and the hot key for the item is ##.

3. Request data as follows

      SendMessage( hwndProgMan, WM_DDE_REQUEST, hwndApp, lParam );

   where the lParam HIWORD is the item's DDE number obtained in step 2.

4. The data is returned in lParam of WM_DDE_DATA message. The DDE data

   value is a string for AppDescription and AppWorkingDir DDE

   transactions. For AppIcon, the data value has the following

   structure:

      typedef struct _PMIconData {

         DWORD dwResSize;

         DWORD dwVer;

         BYTE iResource;  // icon resource

      } PMICONDATA, *LPPMICONDATA;

   To create the icon, the application must call:

      hIcon = CreateIconFromResource((LPBYTE)&(lpPMIconData->iResource),

                  lpPMIconData->dwResSize,

                  TRUE,

                  lpPMIconData->dwVer

              );

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrDde


INF: Win32 Drag and Drop Server

Article ID: Q105530

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The supported method for creating a drag and drop server is to use OLE

(Object Linking and Embedding) version 2.0. This works on Windows and

Windows NT and will work on future versions of these operating

systems.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrDnd


FIX: Low Memory Condition Cause APIs to Return Random Values

Article ID: Q105575

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

Low memory on a Windows NT computer can cause USER APIs to return random

values. For example, CreateWindowEx() returns a bad value, and

SetWindowLong() and GetWindowLong() do not receive the correct value.

STATUS

======

Microsoft has confirmed this to be a problem in Windows NT and Windows NT

Advanced Server version 3.1. This problem was corrected in the latest U.S.

Service Pack for Windows NT and Windows NT Advanced Server version 3.1. For

information on obtaining the Service Pack, query on the following word in

the Microsoft Knowledge Base (without the spaces):

   S E R V P A C K

Additional reference words: 3.10

KBCategory: Prg

KBSubCategory: UsrMisc


INF: Development Tools Do Not Accept Unicode Text

Article ID: Q106065

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Neither the Win32 SDK tools or Visual C++ (VC++) support Unicode text.

In fact, the C/C++ Language specification says that the source files

are to be written in 7-bit ANSI.

MORE INFORMATION

================

For example, language-specific resources cannot be specified in Unicode in

the .RC file because RC does not accept the Unicode text. Although the

message compiler has flags for Unicode, the flags are not implemented.

To convert to and from Unicode text, use the UCONVERT utility included in

your MSTOOLS\BIN directory. The source for UCONVERT is in

MSTOOLS\SAMPLES\SDKTOOLS\UCONVERT.

The long term solution that Microsoft is working on are Resource

Localization Tools and other methods that will allow the user to localize

the strings in a GUI editor, running on the target machine.

Note that it is possible to specify Unicode escapes in L-quoted strings.

The following is quoted from "Common Statement Parameters" in RC.HLP:

   By default, the characters listed between the double quotation

   marks are ANSI characters and escape sequences are interpreted as

   byte escape sequences. If the string is preceded by the L prefix,

   the string is a wide-character string and escape sequences are

   interpreted as two-byte escape sequences that specify Unicode

   characters. If a double quotation mark is required in the text, you

   must include the double quotation mark twice or use the \" escape

   sequence.

Another alternative is to use user-defined resources and include a binary

(Unicode) file.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrNls


INF: Identifying a Previous Instance of an Application

Article ID: Q106385

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The entry point of both Windows and Windows NT applications is documented

to be:

   int WinMain( hInstance, hPrevInstance, lpszCmdLine, nCmdShow )

   HINSTANCE hInstance;        /* Handle of current instance  */

   HINSTANCE hPrevInstance;    /* Handle of previous instance */

   LPSTR lpszCmdLine;          /* Address of command line     */

   int nCmdShow;               /* Show state of window            */

However, under Windows NT, hPrevInstance is documented to always be NULL.

The reason is that each application runs in its own address space and may

have the same ID as another application.

To determine whether another instance of the application is running, use a

named mutex. If opening the mutex fails, then there are no other instances

of the application running. FindWindow() can be used with the class and

window name. However, note that a second instance of the application could

be started, and could execute the FindWindow() call before the first

instance has created its window. Use a named object to ensure that this

does not happen.

MORE INFORMATION

================

The fact that hPrevInstance is set to NULL simplifies porting Win16

applications. Most Win16 applications contain the following logic:

   if( !hPrevInstance )

      if( !InitApplication(hInstance) )

         return FALSE;

Under Windows, window classes only are registered by the first instance of

an application. Consequently, if hPrevInstance is not NULL, then the window

classes have already been registered and InitApplication() is not called.

Under Windows NT, because hPrevInstance is always NULL, InitApplication()

is always called, and each instance of an application will correctly

register its window classes.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrMisc


INF: Retrieving DIBs from the Clipboard

Article ID: Q106386

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Retrieving a DIB (device-independent bitmap) from the clipboard can take

significantly more time than retrieving a bitmap from the clipboard. The

difference stems from the fact that a bitmap is a GDI object and a DIB is a

global memory object.

MORE INFORMATION

================

When SetClipBoardData() is passed a global memory handle, as it is when it

is passed a handle to a DIB, all the data gets copied into the Win32 server

and put into a sharable section of memory. When the DIB is retrieved with

GetClipBoardData(), the shared memory is mapped into the application's

virtual address space and the memory handle is cached. Any subsequent calls

to GetClipBoardData() return quickly, because the memory does not have to

be remapped.

In contrast, when retrieving a bitmap with GetClipBoardData(), only a

handle is created, because a bitmap is a GDI object.

When CloseClipboard() is called, all of the cached handles to shared memory

and GDI objects are deleted.

Rather than reopening the clipboard, it is a good idea to keep a local copy

of anything retrieved from the clipboard if the item will be used again

after the clipboard has been closed. In general, data should be retrieved

from the clipboard only when the application is doing a paste or if the

application is a clipboard viewer processing a WM_DRAWCLIPBOARD message.

The data for a GDI object exists on the server side. In other words,

bitmaps and DDBs (device-dependent bitmaps) exist in the Win32 subsystem

address space. Only the handles of GDI objects are private to an

application. Therefore, to make a bitmap or a DDB accessible to another

application, only a call to DuplicateHandle() is needed.

Note that even though it is faster to retrieve a DDB from the clipboard, it

is still recommended to put a DIB on the clipboard rather than a DDB.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrClp


INF: Using SendMessageTimeout() in a Multithreaded Application

Article ID: Q106716

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

SendMessageTimeout() is new to the Win32 application programming interface

(API). The function sends a message to a window and does not return until

either the window procedure processes the message or the timeout occurs.

MORE INFORMATION

================

This article uses the following scenario to illustrate the behavior of this

function:

Suppose that Win1 and Win2 are created by the same application and

that the following code is included in their window procedures:

   <WindowProc for window Win1>

      ...

      case <xxx>:

         ...

         SendMessageTimeout(      hWnd2,   // window handle

                              WM_USER+1,   // message to send

                                 wParam,   // first message parameter

                                 lParam,   // second message parameter

                            SMTO_NORMAL,   // flag *

                                    100,   // timeout (in milliseconds)

                                   &ret ); // return value

        ...

         break;

      case WM_USER+2:

        <time-consuming procedure>

         break;

* Note that the SMTO_NORMAL flag indicates that the calling thread can

process other requests while waiting for the API to return.

   <WindowProc for window Win2>

      ...

      case WM_USER+1:

         ...

         SendMessage(     hWnd1,    // window handle

                      WM_USER+2,    // message to send

                         wParam,    // first message parameter

                         lParam );  // second message parameter

         OtherStuff();

         ...

         break;

If Win1 executes this SendMessageTimeout() and Win2 uses SendMessage() to

send a message to Win1, Win1 can process the message because SMTO_NORMAL

was specified. If the SendMessageTimeout() expires while the execution is

currently in the window procedure for Win1, the state of the system will

depend on who owns the windows.

If both windows were created by the same thread, the timeout is not used

and the process proceeds exactly as if SendMessage() was being used. If the

windows are owned by different threads, the results can be unpredictable,

because the timeout is restarted whenever a message or some other system

event is received and processed. In other words, the receipt by Win1 of

WM_USER+2 causes the timeout to restart after the message is processed. If

the function executed by Win2, OtherStuff(), then uses up more than 100

milliseconds without awakening the thread that created Win1, the original

SendMessageTimeout() will timeout and return. The OtherStuff() function

continues to completion but any value that was to be returned to Win1 will

be lost. Note that the code paths will always complete.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrMisc


INF: Journal Hooks and Compatibility

Article ID: Q106717

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Journal hooks are used to record and play back events, such as keyboard and

mouse events. Journal hooks are system-wide hooks that take control of all

user input, and therefore should be used as little as possible.

MORE INFORMATION

================

Note that Windows NT does not ship with a Recorder application, as Windows

3.1 does. Therefore, it may be desirable to create an application that can

play back macros recorded under Windows 3.1. However, there are a number of

different problems with the Windows NT implementation of journaling that

make it difficult to use macros recorded under Windows 3.1.

For example, under Windows 3.1 you can distinguish between the LEFT SHIFT

and RIGHT SHIFT keys, while in Windows NT only virtual keys are used, thus

a distinction between the left and the right is not recorded or used in

playback.

The EVENTMSG structures recorded under Windows 3.1 that hold keystrokes do

not play back under Windows NT. They must be modified, because the journal

playback hook parses a scan code out of the EVENTMSG structure differently

than the Windows 3.1 journal record hook put it in the structure. Under

Windows 3.1, paramH specifies the repeat count. Under Windows NT, there is

no way to specify a repeat count; it is always assumed to be 1.

For more information on hooks, please see the Hooks Overview in Volume 1 of

the Win32 "Programmer's Reference" and the article "Win32 Hooks" included

in the MSDN CD #5.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrHks


INF: Hooking Console Applications and the Desktop

Article ID: Q108232

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Under Windows NT, system hooks are limited in two situations: hooking

console windows and hooking the desktop.

Because of the current design of the console and the fact that its user

interface runs in the Win32 server, Windows NT does not support hook calls

in the context of console applications. Thus, if application A sets a

system-wide input hook and text is typed in a console window, application

A's input hook will not be called. The same is true for every type of

Windows hook except for journal record and journal playback hooks.

MORE INFORMATION

================

Windows NT supports journaling by forcing the console input thread to

communicate with the application that set the hook. In the case of a

console, the call to the hook functions are run in the context of the

application that installed the hook. This forces Windows NT to

synchronously talk to this process in order for it to work; if this process

is busy or blocked (as it is when it is sitting at a breakpoint), the

console thread is hung.

If console applications were typical Win32 applications, then this would

not be a problem. A design change such as this would require that each

console take an extra thread just to process input. This was not acceptable

to the designers, and therefore console applications are not implemented in

the same way that other Win32 processes are implemented.

Similarly, if Windows NT allowed other hooks to freely hook any process,

then these processes could enter a hanging state as well. The reason that

journaling is allowed to hook consoles is that journaling already requires

synchronization between all processes in the system, and a mechanism to

disengage the journaling process (via the CTRL+ESC, ALT+ESC and

CTRL+ALT+DEL keystroke combinations) is provided to prevent hanging the

system message queue.

For similar reasons, 16-bit Windows applications cannot hook 32-bit Windows

applications under Windows NT.

The issues above apply equally well to hooking the desktop. If an

application were allowed to hook the desktop, it could potentially hang it.

This is completely unacceptable and violates one of the design principles

of Windows NT: no application should be allowed to bring down the system or

hang the user interface.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrHks


PRB: GetOpenFileName() and Spaces in Long Filenames

Article ID: Q108233

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

GetOpenFileName() is the application programming interface (API) for the

open file common dialog box. This API displays the long filenames (LFNs) on

NTFS and HPFS.

When using the OFN_ALLOWMULTISELECT flag with the GetOpenFileName() API,

the dialog box automatically presents the 8.3 names for all LFNs that

contain embedded spaces.

CAUSE

=====

The original design of GetOpenFileName() uses a filename list that is space-

delimited when the OFN_ALLOWMULTISELECT flag is specified. Thus, there is

no programmatic way to determine which string tokens are complete filenames

or fragments of a complete name with spaces.

STATUS

======

This behavior is by design. Microsoft is considering changing this behavior

in a future release of Windows NT.

MORE INFORMATION

================

Historically, FAT filenames that contained embedded spaces were branded as

"illegal," even though the specifications of the FAT file system do not

impose such a restriction. For example, many of the MS-DOS command-line

utilities do no allow the user to specify filenames with embedded spaces,

because of difficulties that would be introduced in parsing the command

line. Under Windows NT, the command utilities have been enhanced to support

such names if they are in quotation marks.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrCmnDlg


INF: MultiByteToWideChar() Codepages CP_ACP/CP_OEMCP

Article ID: Q108450

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

MultiByteToWideChar() maps a character string to a wide-character string.

The declaration of this application programming interface (API) is as

follows:

   int MultiByteToWideChar(uCodePage, dwFlags, lpMultiByteStr,

      cchMultiByte, lpWideCharStr, cchWideChar)

   UINT uCodePage;         /* codepage                        */

   DWORD dwFlags;          /* character-type options           */

   LPCSTR lpMultiByteStr;  /* address of string to map         */

   int cchMultiByte;       /* number of characters in string   */

   LPWSTR lpWideCharStr;   /* address of wide-character buffer */

   int cchWideChar;        /* size of wide-character buffer    */

The first parameter, uCodePage, specifies the codepage to be used when

performing the conversion. This discussion applies to the first parameter

of WideCharToMultiByte() as well. The codepage can be any valid codepage

number. It is a good idea to check this number with IsValidCodepage(), even

though MultiByteToWideChar() returns an error if an invalid codepage is

used. The codepage may also be one of the following values:

   CP_ACP       ANSI codepage

   CP_OEMCP     OEM (original equipment manufacturer) codepage

CP_ACP instructs the API to use the currently set default Windows ANSI

codepage. CP_OEMCP instructs the API to use the currently set default OEM

codepage.

If Win32 ANSI APIs are used to get filenames from a Windows NT system, use

CP_ACP when converting the string. Windows NT retrieves the name from the

physical device and translates the OEM name into Unicode. The Unicode name

is translated into ANSI if an ANSI API is called, then it can be translated

back into Unicode with MultiByteToWideChar().

If filenames are being retrieved from a file that is OEM encoded, use

CP_OEMCP instead.

MORE INFORMATION

================

When an application calls an ANSI function, the FAT/HPFS file systems will

call AnsiToOem(); however, if an ANSI character does not exist in an OEM

codepage, the filename will not be representable. In these cases,

SetFileApisToOEM() should be called to prevent this problem by setting a

group of the Win32 APIs to use the OEM codepage instead of the ANSI

codepage.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrNls


INF: Replacing Windows NT 3.1 Control Panel's Mouse Applet

Article ID: Q110704

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The Control Panel includes a Mouse applet as a standard applet that is

shipped with the system. In Windows 3.1, this applet can be overridden by

an ISV/OEM's mouse driver or module. Windows 3.1 accomplished this by the

Control Panel doing a GetModuleHandle() call on "Mouse". If MOUSE.DLL or

MOUSE.EXE was already loaded in the system, Control Panel would look for

the entry point "CPlApplet". If found, Control Panel would send the

following messages:

   CPL_NEWINQUIRE

   -or-

   CPL_INQUIRE (the former is preferred)

This would return the icon and strings to replace the mouse icon already in

Control Panel.

In Windows NT, because of the separation of Kernel drivers from

applications by the client-server interface, the GetModuleHandle() call

does not work. Consequently, the same functionality must be achieved in a

slightly different way. The Control Panel calls LoadLibrary( "Mouse" ) to

look for a MOUSE.DLL or a MOUSE.EXE. If this call fails, no other checks

are made.

If LoadLibrary() succeeds, the Control Panel looks for the "CPlApplet"

entry point, sends a CPL_INIT message, and then sends a CPL_NEWINQUIRE. If

CPL_NEWINQUIRE fails, a CPL_INQUIRE is sent; however, it is preferable to

have the applet implement the newer CPL_NEWINQUIRE message. The string

information returned by the CPL_NEWINQUIRE message can be in either UNICODE

or ANSI (UNICODE is preferred) as long as the dwSize field is set

correctly. See the CPL.H public header file for these messages and

structures (for example CPLINFOW or CPLINFOA, where CPLINFOW is the

default).

When the User double-clicks the Mouse applet icon, the MOUSE.DLL or

MOUSE.EXE will receive a CPL_DBLCLK message from the CPlApplet interface.

This routine must return TRUE to the Control Panel if the routine runs its

own dialog. If FALSE is returned, the internal Mouse Dialog box will be

presented to the User.

The Control Panel will send the CPL_EXIT message to the Mouse applet when

it wants to unload the module or terminate. The applet must use this

message to perform tasks such as calling UnRegisterWindowClass(), freeing

memory, and unloading DLLs.

NOTE: It is not possible to replace any of the other standard Windows NT

3.1 Control Panel applets.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: UsrMisc


DOCERR: DragQueryFile() Return Code Can Be Misleading

Article ID: Q115081

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The documentation for DragQueryFile() in the "Win32 Programmer's

Reference" indicates that the return value is "the count of the

characters copied" or "the required size, in characters, of the buffer".

However, the actual return values do not include the trailing null

character in this count.

RESOLUTION

==========

The correct description for the return value is "the length of the string

returned, not including the terminating null character" or "the length of

the string that would be returned, not including the terminating null

character".

Additional reference words: 3.10

KBCategory: Ref

KBSubcategory: UsrDnd


INF: General Overview of Win32s

Article ID: Q83520

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

SUMMARY

=======

The following is intended as a general introduction to Win32s. More

information can be found in the "Win32s Programmer's Reference" and by

querying for Knowledge Base articles on "Win32s".

MORE INFORMATION

================

General Overview

----------------

The Win32 API consists of the Window 3.1 (Win16) API, with types stretched

to 32 bits, plus the addition of APIs which offer new functionality, like

threads, security, services, and virtual memory. Applications developed

using the Win32 API are called "Win32 applications".

Win32s is a set of DLLs and a VxD which allow Win32 applications to run on

top of Windows or Windows for Workgroups version 3.1. Win32s supports a

subset of the Win32 API, some directly (like memory management) and some

through thunks to the 16-bit systems (particularly GDI and User). Win32s

contains function stubs for the APIs that are not supported, which return

ERROR_NOT_IMPLEMENTED. Win32s also includes 4 new APIs which support the

Universal Thunk (UT). For details on which API are supported under Win32s,

refer to the individual API entries in the help file "Win32 API Reference."

Among the new features gained from Win32 are structured exception handling

(SEH), FP emulation, memory-mapped files, named shared memory, and sparse

memory.

Win32 applications running on Windows 3.1 will generally be faster than

their Win16 equivalents on Windows 3.1, particularly if they are memory or

floating-point intensive. The actual speed improvement varies with each

application, because it depends on how often you cross the thunk layer.

Each call which uses a thunk is no more than 10 percent slower than a

direct call.

Binary Compatibility

--------------------

Win32s offers binary compatibility for Win32 application on Windows 3.1 and

Windows NT.

When you call a Win32 API, two options should be allowed:

 - Option A: Your code should allow for a successful return from the

   function call.

 - Option B: Your code should allow for an unsuccessful return from

   the function call.

For example, if the application is running under Windows 3.1 and a call is

made to one of the supported APIs, then the call returns successfully and

option A is executed. If the call is made while running under Windows NT,

the call again returns successfully and option A should be executed.

However, if running under Windows 3.1 and a Win32 API function is called

that is unsupported, then an error code is returned and option B should be

executed.

If, for example, option A were using a CreateThread() call, then option B

would be alternative code, which would handle the task using a single-

thread solution.

Programming Issues

------------------

Win32 applications cannot use DOS and BIOS interrupts; therefore, the

Win32s VxD has Win32 entries for each Interrupt 21 and the BIOS calls.

The Win32s DLLs may thunk to Win16 when a Win32 application makes a call.

The 32-bit parameters are copied from the 32-bit stack to a 16-bit stack

and the 16-bit entry point is called.

There are other semantic difference between Windows 3.1 and Win32. Windows

3.1 will run applications for Win32 nonpreemptively in a single, shared

address space, while Windows NT runs them preemptively in separate address

spaces. It is therefore important that you test your Win32 application on

both Windows 3.1 and Windows NT.

If you need to call routines that reside in a 16-bit DLL or Windows from 32-

bit code, you can do this using the Win32s Universal Thunk, RPC, or other

client-server techniques. For a description of UT, please see the "Win32s

Programmer's Reference" and the sample UTSAMPLE.

DDE, OLE, WM_COPYDATA, the clipboard, metafiles, and bitmaps can be used

between Win16 and Win32 applications on both Windows 3.1 and Windows NT.

Additional reference words: 1.10

KBCategory: Prg

KBSubcategory: W32s


PRB: Win32s GetVolumeInformation() Returns 0x12345678

Article ID: Q93639

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.0 and 1.1

----------------------------------------------------------------------

SYMPTOMS

========

In Win32s version 1.0 and 1.1, GetVolumeInformation() always returns a

volume ID of 0x12345678.

STATUS

======

This is a known limitation of Win32s and is by design.

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Calling a Win32 DLL from a Win16 App on Win32s

Article ID: Q97785

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

SUMMARY

=======

A Windows version 3.1 application can call a Win32 dynamic-link library

(DLL) under Win32s using Universal Thunks.

The following are required components (in addition to the Windows 3.1

application and the Win32 DLL):

 - A 16-bit DLL that provides the same entry points as the Win32 DLL.

   This serves as the 16-bit end for the Universal Thunk. The

   programmer must also include code that will detect whether the

   32-bit side is loaded.

 - A Win32 DLL that sets up the Universal Thunk. This serves as the

   32-bit end of the Universal Thunk. This DLL is supported only under

   Win32s.

 - A Win32 EXE that loads the 32-bit DLL described above.

The following diagram illustrates how the pieces fit together:

                     -----------    -----------     ---------

                     | Win32 EXE |-->| Win32 DLL |<->|  Win32  |

    32-bit           |   (stub)  |   |    (UT)   |   |   DLL   |

                     -----------    -----------     ---------

                              /|\      /|\

             -----------------|--------|-------------------------

                               |       \|/

                ---------    ------------

               | Win 3.1 |<->| 16-bit DLL |

    16-bit     |   app.  |   |   (UT)     |

                ---------    ------------

MORE INFORMATION

================

The load order is as follows: The Windows 3.1 application loads the 16-bit

DLL. The 16-bit DLL checks to see whether the 32-bit side has been

initialized. If it has not been initialized, then the DLL spawns the 32-bit

EXE (stub), which then loads the 32-bit DLL that sets up the Universal

Thunks with the 16-bit DLL. Once all of the components are loaded and

initialized, when the Windows 3.x application calls an entry point in the

16-bit DLL, the 16-bit DLL uses the 32-bit Universal Thunk callback to pass

the data over to the 32-bit side. Once the call has been received on the 32-

bit side, the proper Win32 DLL entry point can be called.

Note that the components labeled Win32 DLL (UT) and Win32 DLL in the

diagram above can be contained in the same Win32 DLL. Remember that the

code in the Win32 DLL (UT) portion isn't supported under Windows NT, so

this code must be special-cased if the DLLs are combined.

For more information, please see the "Win32s Programmer's Reference."

Additional reference words: 1.10 reverse universal thunk

KBCategory: Prg

KBSubcategory: W32s


INF: Win32s Message Queue Checking

Article ID: Q97918

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

Win32 applications that are designed to run with Win32s need to check

the message queue through a GetMessage() or PeekMessage() call to

avoid locking up the system. With Windows NT this is not a problem

because the input model is desynchronized. That is, each thread has

its own input event queue rather than having one queue for the entire

system. In a synchronous input model, one application can block all of

the others by allowing the single system queue to fill up with its

messages. With Windows NT, an application that lets its input queue

fill up will not affect other applications.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: W32s


PRB: _getdcwd() Returns the Root Directory Under Win32s

Article ID: Q98286

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

SYMPTOMS

========

In the following code segment, _getdcwd() always returns the root:

   _getdcwd( 3, cBuf, MAX_PATH );

   MessageBox( hWnd, cBuf, "Drive 3 <C drive>", MB_OK );

Also, in the following code segment, _chdrive() and _getcwd() always return

the root:

   _chdrive( 3 );

   _getcwd( cBuf, MAX_PATH );

   MessageBox( hWnd, cbuf, "Drive 3 <C drive>", MB_OK );

CAUSE

=====

When a Win32 application starts on Win32s, the root is set as the current

directory for any drive except the default drive.

RESOLUTION

==========

The following code fragments work as expected under Win32s:

   _getdcwd( 0, cBuf, MAX_PATH );

   MessageBox( hWnd, cBuf, "Drive 0 <default drive>", MB_OK );

-or-

   GetCurrentDirectory( sizeof (cBuf), cBuf );

   MessageBox( hWnd, cBuf, "SCD", MB_OK );

MORE INFORMATION

================

Windows NT uses the current directory of a process as the initial current

directory for the current drive of a child process. So for example, if the

current directory in the command prompt (CMD.EXE) is C:\WINNT then the

current directory of the child process will be C:\WINNT.

However, on Win32s the current directory for any drive except the default

drive is set to the root and not the current directory of the parent

process. A Win32 application running on Win32s calling _chdrive() or

SetCurrentDirectory() to change the drive GetCurrentDirectory or _getcwd()

will then return the root. The _getdcwd() function is a composite of

changing drives, getting the current directory of that drive, and change

back to the original drive. Therefore, _getdcwd() will always return the

root on Win32s.

Running the following sample to display the current directory of drives C

and D under Windows NT properly displays the full path of the drive.

Running the sample under Win32s always displays the root ("C:\", "D:\").

Sample Code

-----------

#include <direct.h>

...

   status =  _getdcwd(3, szPath, MAX_PATH);    // drive 3 == C:

   if( status != NULL )

   {

      MessageBox( hWnd, szPath, "Current working directory on C:", MB_OK );

   }

   status =  _getdcwd( 4, szPath, MAX_PATH );  // drive 4 == D:

   if( status != NULL )

   {

      MessageBox( hWnd, szPath, "Current working directory on D:", MB_OK );

   }

...

Additional reference words: 1.10

KBCategory: Prg

KBSubcategory: W32s


FIX: GetVersion() Returns Invalid Value Under Win32s

Article ID: Q98723

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.0

----------------------------------------------------------------------

SYMPTOMS

========

In Win32s version 1.0, GetVersion() returns a value of 0x80000A3f, which

equates to 3F.0A--Win32s version 61.10.

CAUSE

=====

An internal build number was OR'ed into the low word rather than the high

word of the value returned for the version.

RESOLUTION

==========

This bug only affects applications that ship with Win32s version 1.0.

Applications that plan to ship Win32s version 1.0 applications can check

the return value and translate it to the correct value.

STATUS

======

This problem was fixed in Win32s version 1.1.

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Support for Sleep() on Win32s

Article ID: Q100713

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

The Win32 application programming interface (API) documentation indicates

that Sleep() is supported on Win32s. It is important to note, however, that

the behavior of Sleep() on Win32s is not the same as it is under Windows

NT.

Under Win32s, Sleep() calls Yield(). The Windows version 3.1 Yield()

function yields only if the message queue is empty; therefore, Sleep()

cannot be relied on to do anything. Use a PeekMessage() loop to do idle

time processing.

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Win32s Translated Pointers Guaranteed for 32K

Article ID: Q100833

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

SUMMARY

=======

Translated pointers are guaranteed to be valid only for 32K, rather than

64K, which selectors are usually limited to. This limitation is for

performance reasons.

Selectors are tiled every 32K. A 0:32 pointer can be quickly translated

into a 16:16 pointer, which will be valid for a minimum of 32K. In other

words, the offset portion of the 16:16 pointer is not guaranteed to be 0

(zero) when translated. As a result, even though the translated selectors

have a limit of 64K, the offset passed to the 16-bit side may be as large

as 32K-1.

The alternative is to create a selector for each and every translation,

which is very slow.

MORE INFORMATION

================

For any given address, there are two selectors that point to it, but only

one has a limit less than 32K:

           +-------+-------+-------+-------+-------+-------+

           |Selector 2(64K)|Selector 4(64K)|Selector 6(64K)|

   +-------+-------+-------+-------+-------+-------+-------+

   |Selector 1(64K)|Selector 3(64K)|Selector 5(64K)|       |

   +-------+-------+-------+-------+-------+-------+-------+

   |  32K  |  32K  |  32K  |  32K  |  32K  |  32K  |  32K  |

   +-------+-------+-------+-------+-------+-------+-------+

Under Win32s 16-bit and 32-bit applications share the same global data

space; therefore, it is possible to share a buffer of up to 64K in size

with a far pointer or more than 64K with a huge pointer by doing the

following:

1. Do a GlobalAlloc() on the 32-bit side.

2. Copy the data.

3. Send the handle to the 16-bit side.

4. Get a pointer to the data on the 16-bit side by using GlobalLock().

The translated pointer is valid until the memory is freed. In the future,

however, 16-bit and 32-bit applications may not share the same global data

space. Therefore, the recommendation is to use a buffer that is passed to

UTRegister().

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Debugging Win32s Applications

Article ID: Q102430

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

SUMMARY

=======

To start debugging a Win32s application, make sure that it runs correctly

under Windows NT. Use either WinDbg or NTSD to track down any problems.

Then, install the debugging libraries for Windows 3.1 and the debug version

of Win32s. Hook the machine to another machine running a terminal emulator

and watch for any warnings that are issued. Be sure to select the

Win32sDebug flags carefully--selecting too many will generate more

information than you may care to see; selecting too few may cause you to

miss important information and warnings.

If you need to debug on Win32s, there are currently two options:

 - Use wdeb386 (note that this method is very tricky).

 - Use remote WinDbg (WinDbgRm) if you are not familiar with using a

   kernel debugger. This method requires two machines: a Win32s

   machine to run the application and WinDbgRm and a Windows NT

   machine to run WinDbg.

If you have Microsoft Visual C++ for Windows NT, CodeView for Win32s is an

additional option. CodeView for Win32s is a user-level debugger; remote

debugging is not necessary, and therefore CodeView for Win32s does not

require a second machine.

MORE INFORMATION

================

When performing remote debugging, make sure that the cable is set up

exactly as specified in the Win32s Programmer's Reference. The WinDbgRm

from Win32s 1.0 does not support software flow control, so it is very

important that the hardware flow control is set up properly. If it is not

set up correctly, you will have problems as the buffers overflow.

WinDbg supports XON/XOFF (software) flow control, which means that the

standard 3-wire cable can now be used, although the default is still

hardware handshaking (5-wire cable). To enable XON/XOFF, you must specify

the XON flag in the serial transport parameters on both WinDbg and

WinDbgRm.

To enable XON/XOFF on WinDbgRm:

1. Select Options to bring up the Transport dynamic-link library (DLL)

   dialog box.

2. Select the serial transport and make any needed modifications to

   the communications port or baud rate parameters.

3. Place the XON flag at the end of the Parameters box. For example,

   "COM1:19200 XON". Note that the space is needed.

To enable XON/XOFF on WinDbg:

1. Select Options/Debug DLLs.

2. Select the proper serial transport layer.

3. Choose the Change button.

4. Add XON to the end of the Parameters line: "COM1:19200 XON".

It is very important that both sides of the debugger use the same protocol.

If they do not, both debuggers will probably hang. Also, the remote

debugging environment requires that binaries be located on the same

drive/directory on both the development and target systems. For example, if

WIN32APP.EXE is built from sources in a C:\DEV\WIN32APP directory, the

binary should be located in this directory on both systems. If you build

your source files by specifying fully qualified paths for the compiler, the

compiler will place this information with the debug records which will

allow WinDbg to automatically locate the appropriate source files.

For additional information on remote debugging, please see the "Win32s

Programmer's Reference" which is included with the Win32 SDK.

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: GetCommandLine() Under Win32s

Article ID: Q102762

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

Under Win32s, GetCommandLine() includes the full drive/path of the

executable, while under Windows NT GetCommandLine() does not include the

full path.

When programs are run from the Program Manager or the File Manager on

Windows 3.1, they are spawned using the full path. As a result, argv[0]

will have the complete path. When a Win32s application is spawned by a 16-

bit application, Windows detects that the application is a Win32s

application. The full path is passed to Win32s regardless of whether or not

WinExec() was invoked with the full path. As a result, 32-bit applications

receive the full path.

When a 32-bit application is spawned from a 32-bit application, the 32-bit

kernel passes the information as given by the parent process [that is, if a

32-bit program is started via CreateProcess() from another Win32

application, argv[0] will contain the path that the spawning application

passed in].

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Win32s NetBIOS Programming Considerations

Article ID: Q104314

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.0 and 1.1

----------------------------------------------------------------------

When running your Win32 application under Windows version 3.1, you may

issue a NetBIOS RESET command. Under Windows 3.1, you normally do not issue

a RESET command due to the common name table. Win32s keeps an internal list

of all the names added in the Windows 3.1 NetBIOS name table by Win32

processes. A RESET on Win32s mimics the RESET on Windows NT by clearing the

names added by that process from the system-wide name table. As a result,

issuing a RESET command as the first NetBIOS command (as required by

Windows NT) on Win32s does not clear out all of the names.

There is also no need to page lock the NetBIOS post routine code under

Win32s. NetBIOS post routine on Win32s is not called at interrupt time. The

post routine is called in the context of the process, and therefore there

is no need to page lock the post routine code.

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Win32s Cannot Support _environ in DLLs

Article ID: Q105680

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

The _environ variable is a pointer to the strings in the process

environment, and is used by the C Run-time routines getenv() and _putenv().

The _environ variable cannot be supported in Win32s dynamic-link libraries

(DLLs) because per-process data is not available. It is not possible to

represent the unique environment of each application in this situation.

Attempting to use _environ in a DLL under Win32s in an application that was

linked with CRTDLL results in the following error:

   The procedure entry point "_environ_dll" could

   not be located in the Dynamic Link Library

   "CRTDLL.dll".

Instead, use GetEnvironmentStrings() and GetEnvironmentVariable().

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Debugging Universal Thunks

Article ID: Q105756

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

The general recommendation for an application targeted for Win32s is to

debug it under Windows NT, then make sure that the application works under

Win32s. However, Universal Thunks are not supported on Windows NT, so it is

not possible to debug applications that use the Universal Thunk in this

manner.

To debug across the Universal Thunk, you can use WDEB386, which is

available with the Windows 3.1 Software Development Kit (SDK). If you are

not familiar with WDEB386, you may find it simpler to use other methods. In

that case, be sure to install the debug version of Windows 3.1 and the

debug version of Win32s and enable suitable notifications for Win32s

(unimplemented functions and messages, verbose, and so forth). You may find

OutputDebugString() useful for displaying extra information.

For more information on WDEB386, please see the Knowledge Base article

"Tips On Installing WDEB386." For information on installing the debug

version of Windows, please see your Windows SDK documentation.

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Using Windows Sockets Under Win32s and WOW

Article ID: Q105757

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

SUMMARY

=======

Win32s versions 1.1 and later provide a thunking layer for Windows Sockets.

A 16-bit Windows Sockets 1.1 package must be installed on the Windows

machine. Otherwise, the system will report that WINSOCK.DLL was not found.

Windows NT provides a versions 1.0- and 1.1-compliant WOW (Windows on

Win32) thunking layer.

MORE INFORMATION

================

There are a number of vendors that sell Windows Sockets packages. Windows

Sockets support is available from Microsoft for LAN Manager version 2.2 for

MS-DOS and Windows 3.1 at no additional cost. Similar support is also being

shipped in "Microsoft TCP/IP for Windows For Workgroups" and the "Microsoft

Network Client."

If you have LAN Manager with Microsoft TCP/IP, you can pick up everything

you need from ftp.microsoft.com. Or, call Microsoft Sales at (800) 426-

9400.

There are two Internet mailing lists for Windows Socket programming

information. The following is information on how to subscribe as of this

date (10/93):

   Send mail to listserv@sunsite.unc.edu with a body that has

   SUBSCRIBE WINSOCK <your_full_internet_email_address>. If you want

   to be on the winsock hackers mailing list, substitute

   WINSOCK_HACKERS for WINSOCK in a separate piece of email.

Additional reference words: 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Win32s and Windows NT Timer Differences

Article ID: Q105758

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

Under Windows NT, timers are system objects; as such, they are not owned by

an application. SetTimer() can be called from within one application with a

handle to a window that was created by a different application. This

application would process the WM_TIMER messages in the window procedure.

The timer event will continue to occur even after the application that

created the timer has terminated. Note that it is fairly uncommon for a

Win32 application to create a timer for another application, but this

method does work.

Because Win32s runs on top of Windows 3.1 and shares many of its

characteristics, timers are owned by the application that calls SetTimer().

The timer event terminates when the application that owns the timer

terminates.

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Using Serial Communications Under Win32s

Article ID: Q105759

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

Windows NT and Windows provide significantly different serial

communications application programming interfaces (APIs). Win32s does not

support the Win32 Communications API.

A good approach to take in writing a Win32 application targetted for Win32s

that uses serial communications is to create a pair of dynamic-link

libraries (DLLs) with the same name. One DLL will use Win32 Communications

APIs and be installed under Windows NT. The other DLL will use the

Universal Thunk to call a 16-bit DLL that will call the Windows

Communications API. This DLL will be installed under Win32s.

For more information on the Universal Thunk, see the "Win32s Programmers

Guide" included with the Software Development Kit (SDK). In addition, there

is a sample in MSTOOLS\WIN32S\UT\SAMPLES\UTSAMPLE.

Additional reference words: 1.00 1.10 comm

KBCategory: Prg

KBSubcategory: W32s


INF: Using VxDs and Software Interrupts Under Win32s

Article ID: Q105760

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

Calling VxDs directly from Win32 code is not supported under Win32s. Win32s

does not support the VxD interfaces, so the call is handled by the

underlying Windows system. The Win32 application runs with 32-bit stack and

code sections, but Windows expects only 16-bit segments. Therefore, the

calls to the VxD cannot be handled by Windows as expected.

To call software interrupts (such as Interrupt 2F) from a Win32 application

running under Windows 3.1 via Win32s, place the call in a 16-bit dynamic-

link library (DLL) and use the Universal Thunks to access this DLL. To

convert the addresses between segmented and linear address, use

UTSelectorOffsetToLinear() and UTLinearToSelectorOffset().

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Getting Resources from 16-Bit DLLs Under Win32s

Article ID: Q105761

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

A Win32 application running under Win32s can load a 16-bit dynamic-link

library (DLL) using LoadLibrary() and free it with FreeLibrary(). This

behavior is allowed primarily so that GetProcAddress() can be called for

printer driver application programming interfaces (APIs).

Calling FindResource() with the handle that LoadLibrary() returns to the

DLL that it just loaded results in an access violation. However, the Win32

application can use the following APIs with this handle

   LoadBitmap

   LoadCursor

   LoadIcon

because this results in USER.EXE (16-bit) making calls to KERNEL.EXE.

If you go through a Universal Thunk to get raw resource data from the

16-bit DLL, it is necessary to convert the resource to 32-bit format,

because the resource format is different from the 16-bit format. The 32-bit

format is described in the Software Development Kit (SDK) file

DOC\SDK\FILEFRMT\RESFMT.TXT.

To determine whether a DLL is a 32-bit or 16-bit DLL, check the DLL header.

The DWORD at offset 0x3C indicates where to look for the PE signature.

Compare the 4 bytes there to 0x00004550 to determine whether this is a

Win32 DLL.

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Sharing Memory Between 32-Bit and 16-Bit Code on Win32s

Article ID: Q105762

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

Memory allocated by a Win32 application using GlobalAlloc() can be shared

with a 16-bit Windows application on Win32s. If the memory is allocated

with GMEM_MOVEABLE, then GlobalAlloc() returns a handle and not a pointer.

The 16-bit application can use the low word of this handle. The high word

is all zeros. Make sure to lock the handle using GlobalLock() in the 16-bit

application to get a pointer.

NOTE: GlobalAlloc (GMEM_FIXED...) is not the same as

GlobalFix(GlobalAlloc(GMEM_MOVEABLE...)). GMEM_FIXED will allocate locked

pages, which is most often not what you want.

Memory allocated by a 16-bit application via GlobalAlloc() must be fixed

via GlobalFix() and translated before it can be passed to a Win32

application. Whenever a Windows object is passed to a Win32 application by

its 32-bit address, the memory must be fixed, because the address is

computed from the selector base only once. If Windows moves the memory, the

linear address used by the Win32 application will no longer be valid.

If you are using the Universal Thunk, you can also pass a buffer from a

Win32 application to a 16-bit dynamic-link library (DLL) in the

UTRegister() call. The address is translated for you. Another alternative

is the translation list passed to the callable stubs. Addresses passed in

the translation list will be translated during the thunking process. For

more information on the Universal Thunk, please see the "Win32 Programmer's

Reference."

NOTE: The ability to share global memory handles under Win32s is a result

of the implementation of Windows 3.1, in which all applications run in the

same address space. This is not true of existing Win32 platforms and will

not be true of future Win32 platforms.

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Troubleshooting Win32s 1.1 Installation Problems

Article ID: Q106715

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

SUMMARY

=======

The installation guide for Win32s version 1.1 that is included in the Win32

SDK recommends running Freecell to verify that the installation was

successful. This article discusses some of the errors that may occur when

trying to run Freecell on an unsuccessful install. The article also

contains a list of corrective actions to help you reinstall Win32s.

MORE INFORMATION

================

One of the following errors may occur when running Freecell if the

installation is not successful:

 - File Error: Cannot find OLECLI.DLL

   -or-

 - Win32s - Error:

   Improper installation. Win32s requires WIN32S.EXE and WIN32S16.DLL to

   run. Reinstall Win32s.

   -or-

 - Win32s - Error:

   Improper installation.  Windows requires w32s.386 in order to run.

   Reinstall Win32s.

   -or-

 - Error: Cannot find file freecell.exe (or one of its components)...

Another possible symptom is that the display is corrupted as soon as you

run FreeCell.

Check the following when Win32s does not install correctly:

 - If you are having video problems, check to see if you have an S3 video

   card. Certain S3 drivers do not work with Win32s. Either use the generic

   drivers shipped with Windows or contact your video card manufacturer for

   an updated driver.

 - If you have a printer driver by LaserMaster, delete it or comment it out

   because it interferes with installing Win32s. Then reboot the computer

   so that the changes you made will take effect. After you successfully

   reinstall Win32s, reinstall the driver or remove the comment characters.

   The driver interferes with installing Win32s because the LaserMaster

   drivers create a WINSPOOL device . The extension is ignored when the

   filename portion of a path matches a device name. As a result, when

   Setup tries to write to WINSPOOL.DRV, it fails, because it attempts to

   write to WINSPOOL. In fact, any Win32 application that tries to link to

   WINSPOOL.DRV also fails; however, most Win32 applications that print

   under Win32s do not use the WINSPOOL application programming interfaces

   (APIs) because they are not supported in Win32s. As a result, you can

   usually just disable this driver while installing Win32s and then

   reenable it afterwards.

 - Delete the \WIN32S directory, the \WIN32APP directory, W32SYS.DLL,

   W32S16.DLL, and WIN32S.EXE from your hard drive. Although it is possible

   to install Win32s on top of an old installation of Win32s, it is better

   to remove the old files before installing the new ones.

 - Edit the WIN32S.INI file on your hard drive. Change the line(s) SETUP =

   1 to read SETUP = 0.

 - Make sure that paging is enabled. From the Control Panel, select the 386

   Enhanced icon, choose Virtual Memory, and choose Change. Verify that the

   drive type is not set to none. The type can be set to either temporary

   or permanent.

 - Make sure that SHARE is enabled. Edit AUTOEXEC.BAT and add the following

   line if it is not already there:

      C:\DOS\SHARE.EXE

 - Reboot your computer and reinstall Win32s.

If you still receive errors when running Freecell, compare the binaries on

your hard drive with those on the CD. Use the MS-DOS program FILECOMP.EXE,

COMP.EXE, or FC.EXE and do a binary compare. For example, if you have the

Win32 SDK CD, type the following:

   fc /b <windir>\win32s\w32s.386 <cd>:\mstools\win32s\nodebug\w32s.386

If you have the 32-bit Visual C++ CD, type the following:

   fc /b <windir>\win32s\w32s.386 <cd>:\msvc32s\win32s\retail\w32s.386

The results of the compare will be, "FC: no differences encountered", if

the binaries were correctly installed. If the binaries are not the same,

you might have a bad copy of the files or a bad CD.

As a last resort, you can try reinstalling Win32s that shipped in the

Visual C++ 32-bit edition. There seems to be a slight difference between

the SETUP.EXE program on the Win32 SDK CD and the SETUP.EXE on the Visual

C++ CD. If you try installing from the 32-bit Visual C++ CD, you should NOT

remove the \WIN32APP or \FREECELL directory or any of the Freecell files.

The Visual C++ CD does not contain Freecell.

NOTE: Using Freecell Help will generate errors, including "Routine Not

Found" or "Help Topic Does Not Exist." The generation of these errors has

nothing to do with whether or not Win32s is installed correctly.

FREECELL.HLP was meant to be used with WINHLP32.EXE. FREECELL.HLP uses the

advanced features of WINHLP32 for full-text searching. WINHELP.EXE, which

runs on Windows 3.1, does not support this. As a result, each time

FREECELL.HLP tries to bind the Find button to the full-text searching APIs,

it fails, and Windows Help displays the message box. You can still read

most of the information in the help file. You can use the Search button to

do keyword searches.

Additional reference words: 1.10

KBCategory: Setins

KBSubcategory: W32s


INF: Opening Named Pipes on Win32s

Article ID: Q108403

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

SUMMARY

=======

Win32s 1.1 includes support for client-side named pipes, provided that the

underlying network supports them as well. The pipe must be created by an

application running on network software that supports server-side named

pipes, such as Windows NT.

On Windows NT, the following code will create a pipe named TestPipe:

   HANDLE hPipe;

   hPipe = CreateNamedPipe( "\\\\.\\pipe\\TestPipe",

      PIPE_ACCESS_OUTBOUND,

      PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,

      1,

      BUFSIZE,

      BUFSIZE,

      NMPWAIT_WAIT_FOREVER,

      NULL

   );

On the client side, for example a Windows for Workgroups machine, the

following code can be used by a Win32 application to open the pipe

TestPipe:

   HANDLE hPipe;

   hPipe = CreateFile( "//<server>/pipe/TestPipe",

      GENERIC_READ,

      FILE_SHARE_READ,

      NULL,

      OPEN_EXISTING,

      0,

      NULL

   );

Note the use of forward slashes instead of backslashes in the pipe name. On

Windows NT, the first argument to CreateFile() could be

"\\\\<server>\\pipe\\TestPipe". However, this does not work on Win32s

running on top of Windows for Workgroups. The call above will work on

machines running Win32s and also on machines running Windows NT.

MORE INFORMATION

================

The following code can be used to open the same named pipe from a Win16

application running on Windows for Workgroups:

   HANDLE hPipe;

   OFSTRUCT Info;

   hPipe = OpenFile( "\\\\<server>\\pipe\\TestPipe",

      &Info,

      OF_READ | OF_SHARE_DENY_NONE

   );

Additional reference words: 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: DIB_PAL_INDICES and CBM_CREATEDIB Not Supported in Win32s

Article ID: Q108497

---------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

---------------------------------------------------------------------

The Windows NT implementation of the Win32 application programming

interface (API) includes two new flags, DIB_PAL_INDICES and CBM_CREATEDIB,

that can be used with various device-independent bitmap (DIB) APIs. These

flags are not part of the Win16 API and are not supported in Win32s.

DIB_PAL_INDICES

---------------

In Windows NT, the DIB_PAL_INDICES flag can be used with the following

APIs:

   CreateDIBitmap()

   CreateDIBPatternBrush()

   CreateDIBPatternBrushPt()

   SetDIBits()

   GetDIBits()

   SetDIBitsToDevice()

   StretchDIBits()

When the dwUsage parameter is DIB_PAL_INDICES, the associated DIB does not

have a color table. In this case, the bitmap bits are indices into the

device palette.

Applications written to run on Windows 3.1 or Win32s should use

DIB_PAL_COLORS or DIB_RGB_COLORS instead of DIB_PAL_INDICES.

CBM_CREATEDIB

-------------

In Windows 3.1, CreateDIBitmap() creates a device-dependent bitmap (DDB)

from a DIB definition and optionally initializes the DDB. In Windows NT,

the CBM_CREATEDIB flag can be used with CreateDIBitmap() to create a new

DIB instead of a DDB.

This functionality is not present in Windows 3.1 or Win32s.

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


PRB: "Routine Not Found" Errors in Windows Help

Article ID: Q108722

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

SYMPTOMS

========

When Freecell is running on Win32s, you may get some errors when you try to

use Freecell Help. This has nothing to do with whether or not Win32s is

installed correctly.

When you first open Help in Freecell running on Win32s, you will get a

message box that says, "Routine Not Found."  You will get that same

message box when you choose the Find button.

When you choose any term in Freecell Help that has a dotted underline (a

pop-up hot key), a window pops up but then quickly disappears. You will

then get a message box that reads, "Help Topic Does Not Exist."

CAUSE

=====

FREECELL.HLP was meant to be used with WINHLP32.EXE. FREECELL.HLP uses the

advanced features of WINHLP32.EXE for full-text searching. WINHELP.EXE,

which runs on Windows 3.1, does not support full-text searching.

WINHLP32.EXE does not run on Win32s or Windows 3.1. As a result, everytime

FREECELL.HLP tries to bind the Find button to the full-text searching

functions, it fails, and WinHelp pops up an error message box.

RESOLUTION

==========

You can still read most of the information in Freecell Help. Although you

cannot use the Find button to do full-text searches, you can use the Search

button to do keyword searches. WINHLP32.EXE will not work on a MS-DOS +

Windows + Win32s operating system. If you need to read the pop-up

definitions or use the Find button, you can do so if you run Freecell Help

on the Windows NT operating system.

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Win32s and LAN Manager APIs

Article ID: Q109204

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

NOTE: Win32s provides support for NetBIOS and Windows Sockets.

There is a NETAPI32.DLL shipping with Win32s. However, this doesn't have

support for Microsoft LAN Manager application programming interfaces

(APIs). This is not a bug because LAN Manager APIs are not supported on

Win32s. However, if NETAPI32.DLL is not in the system and an application

uses LAN Manager APIs, NETAPI32.DLL will not load because the loader cannot

resolve the entry-points from the nonexistent dynamic-link library (DLL).

One of the solutions is to use Universal Thunks. Using Universal Thunks,

calls can be made to 16-bit DLLs. Therefore, the 16-bit NETAPI.DLL that

ships with LAN Manager can be accessed by this mechanism.

Sample programs using Universal Thunks are provided in the Win32 SDK and

the Visual C++ SDK. The sample on the Win32 SDK is in the

MSTOOLS\WIN32S\UT\SAMPLES directory. On the Visual C++ for NT CD-ROM, the

sample is located in the MSVC32S\WIN32S\UT\SAMPLES directory.

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubCategory: W32s


INF: Creating Instance Data in a Win32s DLL

Article ID: Q109620

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

SUMMARY

=======

The Win32 dynamic-link libraries (DLLs) that are running on Win32s use

shared data by default. This means that any global data in the DLL is

shared by all processes that use the DLL. Thread local storage (TLS) can be

used to create instance data; that is, data in the DLL that is specific to

each process.

The Win32s "Programmers Reference" mentions that TLS can be used to create

instance data, but provides no details. The sample code below shows the

source for a DLL that uses instance data on both Win32 and Win32s. The

sample code was built using Microsoft Visual C++, 32-bit edition.

If you use a development environment that does not have similar support for

TLS, you should still be able to use the API (application programming

interface) calls. The API calls for TLS are TlsAlloc, TlsGetValue,

TlsSetValue, and TlsFree.

MORE INFORMATION

================

One reason for wanting to create instance data on Win32s is to create a DLL

that behaves identically on Win32s and Win32. Another way to create a DLL

that behaves identically on Win32s and Win32 is to share all of the data in

the Win32 DLL. For additional information, please see the following

article(s) in the Microsoft Knowledge Base:

   ARTICLE-ID: Q109619

   TITLE     : INF: Sharing All Data in a DLL

Sample Code

-----------

/* Compile options used: /LD /MD

*/

int __declspec(thread) nVar = 0;

int __declspec(dllexport) GetVar()

{

    return nVar;

}

void __declspec(dllexport) SetVar(int nNew)

{

    nVar = nNew;

}

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


BUG: Problems with Win32s CreateFileMapping()

Article ID: Q110705

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.1 and 1.1a

----------------------------------------------------------------------

SYMPTOMS

========

The following problems exist with CreateFileMapping() under Win32s versions

1.1 and 1.1a:

Symptom 1

---------

Specifying the SEC_COMMIT flag or the SEC_NOCACHE flag causes the

CreateFileMapping() function to return ERROR_INVALID_PARAMETER.

Symptom 2

---------

No matter what size is specified in CreateFileMapping(), the file size

under Win32s is always a multiple of 4096.

CAUSE

=====

Cause 1

-------

The underlying operating system does not support file-by-file cache/nocache

flags as Windows NT does. By default, writes to a file are cached as are

any other writes on the system. The problem is that Win32s is not ANDing

out these bits before checking for equality with other flags, and therefore

this error occurs.

Cause 2

-------

This is a bug in Win32s.

RESOLUTION

==========

Resolution 1

------------

Do not specify SEC_COMMIT and SEC_NOCACHE under Win32s (an easy way to do

this is to redefine them if Win32s is present).

Resolution 2

------------

None.

STATUS

======

Status 1

--------

The SEC_COMMIT flag should be accepted and the SEC_NOCACHE flag will most

likely be ignored in Win32s version 1.2.

Status 2

--------

Microsoft has confirmed this to be a problem in Win32s version 1.1. This

problem should be fixed in Win32s version 1.2. We will post new information

here in the Microsoft Knowledge Base when it becomes available.

Additional reference words: 1.10 1.10a

KBCategory: Prg

KBSubcategory: W32s


INF: Availability of Win32s 1.1a and Later

Article ID: Q110843

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.1, 1.1a, and 1.15

----------------------------------------------------------------------

SUMMARY

=======

Win32s version 1.1 (build 88) was made available with the final release of

Windows NT. An updated version, version 1.1a (build 89), was shipped with

the Win32 SDK Alpha Update CD.

Win32s 1.1a has fixes for the following bugs:

 - GetModuleFileName() returns byte count+1

 - UT callback returns 32-bit value in EAX, not DX:AX

 - GetModuleFileName() OFSTRUCT.cBytes incorrect

 - LoadLibrary() fails after about 4500 calls

MORE INFORMATION

================

A prerelease version of Win32s version 1.2 was made available at the

December 1993 PDC (Professional Developers Conference). The prerelease

version can be found on the OLE JumpStart CD. This version adds support for

OLE version 2.0.

The beta version of Win32s 1.2 will be made available with the Daytona

beta, along with a release version of Win32s 1.15. Conference attendees and

subscribers to MSDN Level II will receive this beta. To subscribe to MSDN,

please call (800) 759-5474.

The Win32s 1.15 release can also be found on

   CompuServe: MSWIN32 Lib 14, 32s115.zip

          FTP: ftp.microsoft.com /Developer/DevTools/Win32SDK/Win32s115.Zip

Additional reference words: 1.10 1.10a 1.15

KBCategory: Prg

KBSubcategory: W32s


INF: Detecting the Presence of NetBIOS in Win32s

Article ID: Q110844

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

The way to determine whether NetBIOS is present from a Win32 application

running on Win32s is to issue an invalid NetBIOS command (such as 0xB2) and

check that the return code is 0x3 (Illegal command).

Additional reference words: 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: How Win32 Applications Are Loaded Under Windows

Article ID: Q110845

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

SUMMARY

=======

Microsoft Win32s is an operating system extension that allows Win32

applications to be run on Windows 3.1. Win32s consists of a VxD and a set

of dynamic-link libraries (DLLs).

It is possible to distinguish whether an executable was built for Win32 or

Win16. Win32 executables use the Portable Executable (PE) format, while

Win16 executables use the New Executable (NE) format.

The Windows 3.1 loader was designed to be aware that Win32 applications

would potentially be loaded. When the user starts a Win32 application, the

Windows 3.1 loader tries to load the Win32 application via WinExec().

WinExec() calls LoadModule(), which will fail with an error indicating that

it was passed an .EXE with the PE format. At this point, WinExec() calls a

special function to start up Win32s. This function loads W32SYS.DLL (16-bit

DLL) via LoadModule(). If W32SYS determines that the EXE is indeed a valid

PE file, it calls LoadModule() on WIN32S.EXE (16-bit EXE) (it is similar to

WinOldApp for MS-DOS-based programs running in Windows). WIN32S.EXE

contains the task database, PSP, task queue, and module database.

WIN32S.EXE calls its only function to load the Win32s 16-bit translator

DLL, W32S16.DLL, which does work as a translator between the 32-bit

application and the 16-bit world that it is running in.

MORE INFORMATION

================

Win32 applications are loaded in the upper 2 gigabytes (GB) of the 4 GB

address space under Win32s, whereas Windows NT loads them in the lower 2

GBs. This is because W32S.386, a VxD, allocates the memory, and VxDs get

memory in the 2 GB to 4 GB range.

On Windows 3.1, all applications, even the Win32 applications, share the

same address space, unlike Windows NT where each Win32 application gets its

own address space.

Additional reference words: 1.00 1.10 G byte

KBCategory: Prg

KBSubcategory: W32s


INF: NetBIOS on Win32s Requires GlobalAlloc()'d Memory

Article ID: Q110988

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

SUMMARY

=======

The Windows 3.1 NetBIOS VxD expects memory allocated for the NetBIOS

Control Block (NCB) and the data buffer (NCB.ncb_buffer) to be allocated

with GlobalAlloc(). The VxD will lock the specified memory page.

If a Win32 application running under Win32s passes the Netbios() command

virtual memory, Netbios() will return error 0x22, indicating that there are

too many commands outstanding. On Win32s, each piece of memory that might

pass through Netbios() must be allocated with GlobalAlloc().

Additional reference words: 1.10

KBCategory: Prg

KBSubcategory: W32s


DOCERR: Errors in Win32s Compatibility

Article ID: Q113679

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

The following Win32 API (application programming interface) functions are

listed in the Win32 Programmer's Reference as being supported under Win32s.

This is incorrect. These Win32 APIs are not supported under Win32s:

   GetCharWidth32

   GetKBCodePage

   GetTextExtentPoint32

   ScrollWindowEx

   WNetAddConnection

   WNetAddConnection2

   WNetCancelConnection

   WNetCancelConnection2

   WNetCloseEnum

   WNetConnectionDialog

   WNetDisconnectDialog

   WNetEnumResource

   WNetGetConnection

   WNetGetLastError

   WNetGetUser

   WNetOpenEnum

The following Win32 APIs and messages are not listed in the Win32

Programmer's Reference as being supported under Win32s. This is incorrect

These Win32 APIs and messages are supported under Win32s:

   CopyMemory

   FillMemory

   FormatMessage

   GetThreadSelectorEntry

   LoadLibraryEx

   MoveMemory

   All OLE 1.0 APIs

   TlsAlloc

   ZeroMemory

   WM_COPYDATA

The following Win32 APIs and CRT (C Run-time) routines are supported under

Win32s, with the restrictions noted.

Function                         Associated Restriction

=======================================================================

CreateFileMapping                SEC_COMMIT is supported, but not

                                 SEC_IMAGE, SEC_NOCACHE or SEC_RESERVE

-----------------------------------------------------------------------

CreateDIBitmap                   DIB_PAL_INDICES is not supported

CreateDIBPatternBrush

CreateDIBPatternBrushPt

GetDIBits

SetDIBits

SetDIBitsToDevice

StretchDIBits

-----------------------------------------------------------------------

GetSystemPaletteEntries          The fourth parameter cannot be NULL

-----------------------------------------------------------------------

spawn                            P_WAIT is not supported

=======================================================================

Additional reference words: 1.10

KBCategory: Ref

KBSubCategory: W32s


BUG: Win32s 1.1 Bug List

Article ID: Q113739

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

SUMMARY

=======

The following is a list of known problem in Win32s version 1.1. Microsoft

has confirmed these to be problems in Win32s version 1.1. Problems marked

with a hyphen ("-") will be corrected in Win32s version 1.15. Problems

marked with an asterisk ("*") will be corrected in Win32s version 1.2.

 - Setup fails if there are 40 groups in Program Manager.

 - WinFile generates a general protection (GP) fault while viewing file

   properties.

 - The Universal Thunk (UT) callback returns a WORD, rather than a DWORD.

 - The LA (linear address) Table is limited to 256 entries. This limits the

   number of VirtualAlloc() calls that will succeed.

 - Win32s does not handle paths that contain an ampersand ("&") or a number

   sign ("#").

 - FP (floating point) exceptions are not trapped by SEH (structured

   exception handling. FP exceptions in 32-bit code which are called from

   16-bit code via UT can cause a GP fault in WIN87EM.

 - Thread Local Storage (TLS) data is allocated from a limited heap size.

   This can cause applications that use a lot of TLS data to fail to load.

 - CB_FINDSTRING and LB_FINDSTRINGEXACT are not thunked correctly from  a

   16-bit application to a 32-bit application.

 - Dialog templates passed from a 32-bit applications are corrupted.

 - If a DDE client responds to INITIATE for which it is also the server,

   lParam is packed incorrectly.

 * fstat() always returns that rt_mode is read/write.

 * chdrive() does not retain the current working directory. chdrive()

   always uses the root directory.

 - ChooseFont()'s referenced CHOOSEFONT structure has blue value set to 0

   with CF_EFFECTS.

 - CopyFile() uses the current time rather than the file time.

 - CreateFile() does not parse UNC names correctly.

 - CreateProcess() does not set current directory correctly.

 - CreateProcess() ignores window size and window position.

 - CreateProcess() debug version corrupts the environment if

   lpApplicationName != NULL.

 - CreateProcess() returns failure if the child does not call GetMessage()

   or yield in some way before control goes to the parent.

 - CreateProcess()'s dwFlags is ignored when starting Win16 applications,

   while wShowWindow is always passed.

 - CreateWindowEx()'s CW_USEDEFAULT flag is not handled, which causes

   problems with using WM_VISIBLE.

 - EnumMetaFile()'s handles array is corrupted.

 - EnumPropsEx() enumerates non-existing properties.

 - EqualRect() returns TRUE for rectangles that are lines.

 - FindFirstFile() error code is set to ERROR_NO_MORE_FILES instead of

   ERROR_FILE_NOT_FOUND if there are no matches for the search pattern.

 - FindFirstFile() may use a bad DTA, causing stack corruption.

 - GetClassInfo() WNDCLASS buffer is corrupted if passed an invalid class.

 * GetFileInformationByHandle() support added in version 1.15, but file

   attribute returned is always 0.

 - GetFilePointer() returns valid value when given invalid handle.

 - GetFileSize() moves the file pointer.

 - GetFileVersionSize() causes a GP fault when 16-bit applications for

   Windows call the function from a 32-bit DLL.

 - GetKerningPairs() results are not in Win32 format.

 - GetModuleFileName() causes the OFSTRUCT structure to be truncated in 16-

   bit applications calling this function on a 32-bit DLL.

 - GetModuleFileName()'s char count returned includes the terminating NULL

   character.

 - GetOpenFileName() call fails with OFN_ENABLETEMPLATEHANDLE.

 - GetOpenFileName() has a hook you can use to trap  WM_INITDIALOG to get

   the address of OPENFILENAME struct, but the pointer is  corrupted by the

   next message.

 - GetOutlineTextMetrics() returns OUTLINETEXTMETRIC structure with Windows

   3.1 format rather than Win32 format.

 - GetOutlineTextMetrics()'s OUTLINETEXTMETRIC UnderscorePosition,

   UnderscoreSize, and otmItalicAngle are incorrect.

 - GetSystemInfo() returns an incorrect lpMinimumApplicationAddress and an

   incorrect lpMaximumApplicationAddress.

 - GlobalCompact() exception occurs when the value is larger than available

   memory.

 - HeapAlloc/malloc() are slow because debug check was left in the code.

 - IsCharAlpha() returns 0 for characters 128-255.

 - LoadLibrary() fails to report unsucessful load of 16-bit DLLs (should

   return ERROR_BAD_EXE_FORMAT).

 - LoadLibrary() fails after 4591 calls due to a memory leak.

 - LoadLibrary() was fixed to work from a 32-bit DLL called by a 16-bit

   application.

 - LoadModule() does not pass cmdshow so applications get SW_SHOWNORMAL.

 - LocalAlloc() fixed to work from a 32-bit DLL called by a 16-bit

   application.

 - MultiByteToWideChar() has the wrong string returned with USE_GLYPHCHARS.

 - NetAccessAdd(), NetApiBufferAllocate(), NetUseGetInfo(), and

   NetUserSetGroups() all are not exported by NETAPI32.DLL.

   NOTE: These functions are not supported.

 - OpenFile() does not parse UNC names correctly.

 - PeekMessage() causes RIP in debug windows if hwnd is NULL.

 - PlayMetaFileRecord()'s handles array is corrupted.

 - PolyPolygon() fails with more than 16 polygons.

 - PrintDlg() incorrectly frees global memory and fails with MFC sample.

 - SetClipboardData()'s 32-bit memory is not freed when clipboard is

   emptied.

 - SetErrorMode()'s SEM_NOOPENFILEERRORBOX does not work. The message box

   still appears.

 - SetFilePointer() returns a valid value if given an invalid handle.

 - SetProp()'s seventeeth call fails if lpsz is a string rather than an

   atom.

 - SetWindowLong()'s GWL_USERDATA always returns 1.

 - TrackMenuPopup()'s optional lprc parameter is not handled correctly.

 - waveOutGetDevCaps()'s WAVEOUTCAP buffer not filled correctly for the

   SoundBlaster.

 - waveOutWrite()'s WOM_DONE messages are not posted with multiple buffers

   and loop play.

 * WinExec() will cause 16-bit applications which are launched to GP fault.

Additional reference words: 1.10

KBCategory: Prg

KBSubCategory: W32s


INF: Converting a Linear Address to a Flat Offset on Win32s

Article ID: Q115080

----------------------------------------------------------------------

The information in this article applies to:

  - Microsoft Win32s, versions 1.1 and 1.15

----------------------------------------------------------------------

SUMMARY

=======

Win32s flat code and data selectors are not zero-based. Linear addresses

retrieved through a VxD can be used in a Win32 application running under

Win32s, after one small change is made.

In addition, there are two Universal Thunk APIs that are used to convert

segmented addresses to flat addresses and vice versa.

MORE INFORMATION

================

Linear Address to Flat Address

------------------------------

Win32s does not base linear addresses at 0, so that exceptions will be

generated when null pointers are dereferenced. Therefore, an access

violation occurs when:

1. a 16-bit DLL calls a VxD to retrieve a linear address (the VxD got

   the address by translating a physical address to a linear address)

   through DPMI function 0800h (map physical to linear).

2. the 16-bit DLL returns the address to a 32-bit application through

   the Universal Thunk.

3. the 32-bit application uses this linear address.

In order to convert a linear address (based at 0) to a flat offset, add

the base to the linear address. To do this, get the offset through

GetThreadSelectorEntry() with the DS or CS and then subtract that base from

the linear address that was returned by the VxD.

Segmented Address to Flat Address

---------------------------------

The following Win32s Universal Thunk APIs are used for address

translation:

 - UTSelectorOffsetToLinear (segmented address to flat address)

 - UTLinearToSelectorOffset (flat address to segmented address)

NOTE: In the nested function call

   UTLinearToSelectorOffset( UTSelectorOffsetToLinear( x ) );

where x is a segmented address, you may not necessarily get the original

value of x back. It is by design that the sel:off pair may be different.

If the memory was allocated by a 16-bit application, Win32s does not

have x in its LinearAddress->selector translation tables. Therefore,

when UTLinearToSelectorOffset() is called, new selectors are created.

Additional reference words: 1.10 gpf gp-fault

KBCategory: Prg

KBSubcategory: W32s


PRB: Page Fault in WIN32S16.DLL Under Win32s

Article ID: Q115082

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s, versions 1.1 and 1.15

----------------------------------------------------------------------

SYMPTOMS

========

Start two instances of the Win32 application under Win32s. Close one

instance, then close the other instance. A page fault is generated in

WIN32S16.DLL. Under Win32s, version 1.1, a dialog box appears. Under

Win32s, version 1.15, the error only appears in the output from the debug

version of Win32s.

CAUSE

=====

This problem can be caused by using the static C run-time (CRT) libraries

or using MSVCRT10.DLL. Note that even if the application does not make any

CRT calls, one of its DLLs may call the CRT initialization and cleanup

code. The CRT code makes the following sequence of API calls:

   DeleteCriticalSection

   DeleteCriticalSection

   DeleteCriticalSection

   TlsFree

   VirtualFree

   VirtualFree

   VirtualFree

When the second application instance terminates, it faults before it makes

the call to TlsFree(). The CRT has two blocks, one that contains strings

from the environment and one that contains pointers to the first blocks.

These are allocated by the first process that attach to the DLL. Other

processes that attach do not allocate these blocks. When processes are

terminated, these two blocks are freed. However, this succeeds only when

the process that owns the memory frees them. Any other process that tries

to access these blocks will fail.

RESOLUTION

==========

Because there is no instance data by default under Win32s, DLLs should use

the CRT in a DLL instead of linking to the CRT statically. MSVCRT10.DLL

(which comes with Visual C++) is not compatible with Win32s because

MSVCRT10.DLL falsely assumes that Win32s implements instance data, which is

only available on Windows NT. Therefore, until an updated MSVCRT.LIB file

is released, use CRTDLL.LIB (which comes with the Win32 SDK) because Win32s

has its own CRTDLL.DLL file that was specifically designed for this use.

MORE INFORMATION

================

The real problem is that memory is allocated for several applications. The

allocation is done by the first application. When this application

terminates, it takes with it all of its memory. This means that each time

the remaining applications try to access this memory, an error occurs.

Symptoms include data corruption, hanging, or the WIN32S16.DLL page fault

mentioned above.

Additional reference words: 1.10 1.15

KBCategory: Prg

KBSubcategory: W32s


INF: Win32s Device-Independent Bitmap Limit

Article ID: Q115084

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s, versions 1.1 and 1.15

----------------------------------------------------------------------

Under Win32s, a device-independent bitmap (DIB) is limited to a size of

1024 by 768 pixels at 24 bits per pixel (approximately 2.3 MB). This can

cause a variety of problems to occur, such as painting problems with

SetDIBitstoDevice().

Additional reference words: 1.10 1.15

KBCategory: Prg

KBSubcategory: W32s


PRB: Display Problems with Win32s and the S3 Driver

Article ID: Q117153

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.1 and 1.15

----------------------------------------------------------------------

SYMPTOMS

========

Applications running on Windows 3.1 exhibit no problems when using an S3

driver, with a resolution of 1024x768 and 256 colors. However, the display

is corrupted when Win32 applications, such as FreeCell, run on Win32s in

the same configuration.

CAUSE

=====

This is a known problem with the S3 driver.

A general protection (GP) fault occurs when the display driver is

performing a bit-block transfer (BitBlt). This happens whether or not

Win32s is running. However, when Win32s is not running, Windows recovers

from the faults. When a Win32 application is running, Win32s catches all

exceptions and transfers control to the nearest try/except frame. As a

result, the BitBlt is interrupted.

RESOLUTION

==========

To get versions of the S3 drivers which exhibit these problems to work with

Win32s, edit your SYSTEM.INI file before running any Win32 applications.

In the SYSTEM.INI file, you will find an entry

   aperture-base=100

Change this entry to

   aperture-base=0

Restart Windows and the display problems will no longer occur.

STATUS

======

The S3 driver version 1.3 does not have this problem. Dell and Microsoft

are aware of these problems and are working to make corrected drivers

available.

Additional reference words: 1.10

KBCategory: Prg

KBSubcategory: W32s


INF: Using a Mouse with MEP Under Windows NT

Article ID: Q83300

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The Microsoft Editor (MEP) included with the Win32 Software Development Kit

(SDK) can be used with a mouse to position the cursor.

By default, the mouse is not enabled for MEP. It is necessary to add the

switch "usemouse:yes" (without the quotation marks) to the TOOLS.INI file

under the [m mep] section. The TOOLS.INI file is a text file editable by

MEP or Notepad.

To change the position of the cursor, first position the mouse pointer on

the new location and then click the left mouse button.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMep


INF: RCDATA Begins on 32-Bit Boundary in Windows NT

Article ID: Q84081

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

RCDATA is guaranteed to begin on a DWORD boundary. However, the strings and

the integers specified in the statement are not aligned by the Resource

Compiler (RC).

MORE INFORMATION

================

   RCDATA statement:

   resname RCDATA

   BEGIN

       0,0,

   END

The definition of RCDATA is not changed. The strings and integers

specified in the statement, 0 in this case, are not aligned on the

DWORD boundary. However, the beginning of the data is DWORD-aligned.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsRc


INF: Format for LANGUAGE Statement in .RES Files

Article ID: Q89822

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The syntax for the LANGUAGE statement in the resource script file is given

as follows on page 289 of the Win32 SDK "Tools User's Guide" manual:

   LANGUAGE major, minor

   major

      Language identifier. Must be one of the constants from WINNLS.H

   minor

      Sublanguage identifier. Must be one of the constants from WINNLS.H

For example, suppose that you want to set the language for the resources in

a file to French. For the major parameter, you would choose the following

constant from the list of language identifiers

   #define LANG_FRENCH                  0x0c

and you would have the choice of any of the sublanguages that begin with

SUBLANG_FRENCH in the list of sublanguage identifiers. They are:

   #define SUBLANG_FRENCH               0x01

   #define SUBLANG_FRENCH_BELGIAN       0x02

   #define SUBLANG_FRENCH_CANADIAN      0x03

   #define SUBLANG_FRENCH_SWISS         0x04

RC.EXE does not directly place these constants in the .RES file. It uses

the macro MAKELANGID to turn the parameters into a WORD that corresponds to

a language ID.

MORE INFORMATION

================

The following information is taken from the WINNLS.H file.

   A language ID is a 16-bit value that is the combination of a

   primary language ID and a secondary language ID.  The bits are

   allocated as follows:

      +-----------------------+-------------------------+

      |      Sublanguage ID   |   Primary Language ID   |

      +-----------------------+-------------------------+

       15                   10 9                       0   bit

   Language ID creation/extraction macros:

      MAKELANGID    - Construct language ID from primary language ID and

                      sublanguage ID.

      PRIMARYLANGID - Extract primary language ID from a language ID.

      SUBLANGID     - Extract sublanguage ID from a language ID.

The macros are defined as follows

   #define MAKELANGID(p, s)       ((((USHORT)(s)) << 10) | (USHORT)(p))

   #define PRIMARYLANGID(lgid)    ((USHORT)(lgid) & 0x3ff)

   #define SUBLANGID(lgid)        ((USHORT)(lgid) >> 10)

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsRc


PRB: Selecting Overlapping Controls in Dialog Editor

Article ID: Q90384

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

Create a dialog box using the Dialog Editor. Place a button onto the dialog

box. Create a frame and place it so that it encompasses the button. It is

not possible to select that button with the mouse. However, if the frame is

created before the button and then moved or placed over the button, then it

is possible to select either the frame or the button.

CAUSE

=====

This behavior is by design. When controls are overlapped, the control that

is selected when the mouse is clicked is the one that comes last in

Z-order.

As a special case, it is possible to select a control placed "underneath" a

group box.

RESOLUTION

==========

From the Arrange menu, choose Order/Group. This will bring up a dialog box.

Change the Z-order of the button to be after that of the frame. The Z-order

may also be changed by manually editing the resource file. The controls

that are further down in the file will be "on top."

NOTE: If the frame is selected and is on top of the button, pressing

SHIFT+TAB selects the previous control, which will be the button. This does

not allow the position of the control to be changed with the mouse;

however, it does allow the text and size to be changed.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsDlg


INF: Dynamic Loading of DLLs Under Windows NT

Article ID: Q90745

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

When using LoadLibrary() under Win16 or OS/2, the Dynamic Link Library

(DLL) is loaded only once. Therefore, the DLL has the same address in all

processes. Dynamic loading of DLLs is different under Windows NT.

A DLL is loaded separately for each process because each application has

its own address space, unlike Win16 and OS/2. Pages must be mapped into the

address space of a process. Therefore, it is possible that the DLL is

loaded at different addresses in different processes. The memory manager

optimizes the loading of DLLs so that if two processes share the same pages

from the same image, they will share the same physical memory.

Each DLL has a preferred base address, specified at link time. If the

address space from the base address to the base address plus image size is

unavailable, then the DLL is loaded elsewhere and fixups will be applied.

There is no way to specify a load address at load time.

To summarize, at load time the system:

1. Examines the image and determines its preferred base address and

   required size.

2. Finds the address space required and maps the image, copy-on-write,

   from the file.

3. Applies internal fixups if the image isn't at its preferred base.

4. Fixes up all dynamic link imports by placing the correct address for

   each imported function in the appropriate entry of the Import Address

   Table. This table is contiguous with 32-bit addresses, so 1024 imports

   require dirtying only one page.

MORE INFORMATION

================

The pages containing code are shared, using a copy-on-write scheme. The

term copy-on-write means that the pages are read-only; however, when a

process writes the page, instead of an access violation, the memory manager

makes a private copy of the page and allows the write to proceed. For

example, if two processes start from the same .EXE, both initially have all

pages mapped from the .EXE copy-on-write. As the two processes proceed to

modify pages, they get their own copies of the modified pages. The memory

manager is free to optimize unmodified pages and actually map the same

physical memory into the address space of both processes. Modified pages

are swapped to/from the page file instead of the .EXE file.

There are two kinds of fixups. One is the address of an imported function.

All these fixups are localized in what the Portable Executable (PE)

specification calls the Import Address Table (IAT). This is an array of 32-

bit function pointers, one for each imported API. The IAT is located on its

own page(s), because it is always modified. Calling an imported function is

actually an indirect call through the appropriate entry in this array. In

case that the image is loaded at the preferred address, the only fixups

needed are for imports.

Note that there is an optimization whereby each import library exports a 32-

bit number for each API along with any name and ordinal. This serves as a

"hint" to speed the fixups performed at load time. If the hints in the

program and the DLL do not match, the loader uses a binary search by name.

The other kind of fixup is needed for references to the image's own code or

data when the image can't be loaded at its preferred address. When a page

must be taken out of memory, the system checks to see whether the page has

been modified. If it has not, then the page is still mapped copy-on-write

against the EXE and can be discarded from memory. Otherwise, it must be

written to the page file before it can be removed from memory, so that the

page file is used as the backing store (where the page is recovered from)

rather than the executable image file.

NOTES

=====

The DLL's entry point does not get called for a second LoadLibrary() call

in a process (that is, no second DLL_PROCESS_ATTACH entry). There is one

call to DllEntry/DLL_THREAD_ATTACH per thread no matter the number of times

a thread calls LoadLibrary(). The same goes for FreeLibrary(), but the

DLL_PROCESS_DETACH happens only on the last call (that is, reference count

back to zero for the process).

Global instance data for the DLL is on a per process basis (only one set

per unique process). If it is necessary to ensure that global instance data

is unique for each LoadLibrary() performed in a single process, consider

thread local storage (TLS) as an alternative. This requires multiple

threads of execution, but TLS allows unique data for each ThreadID. There

is very little overhead on the DLL's part; just create a global TLS index

during process initialization. During thread initialization, allocate

memory (via HeapAlloc(), GlobalAlloc(), LocalAlloc(), malloc(), and so on)

and store a pointer to the memory using the global TLS index value in the

function TlsSetValue. Win32 internally stores each thread's pointer by TLS

index and ThreadID to achieve the thread specific storage.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseDll


INF: Use of DLGINCLUDE in Resource Files

Article ID: Q91697

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The Windows 3.1 SDK dialog editor needs a way to know what include file is

associated with a resource file that it opens. Rather than prompt the user

for the name of the include file, the name of the include file is embedded

in the resource file in most cases.

MORE INFORMATION

================

Embedding the name of the include file is done with a resource of type

RCDATA with the special name DLGINCLUDE. This resource is placed into the

.RES file and contains the name of the include file. The dialog editor

looks for this resource when it loads a .RES file. If this resource is

found, then the include file is opened also; if not, the editor prompts the

user for the name of the include file.

In some Windows 3.1 build environments, the dialog editor was used to

create dialogs that were placed in more than one .DLG file. These different

.DLG files were then included in one .RC file, which was compiled with the

resource compiler. Therefore, the resource file gets multiple copies of a

RCDATA type resource with the same name, DLGINCLUDE, but the resource

compiler and dialog editor don't complain.

In the Win32 SDK, changes were made so that this resource has its own

resource type; it was changed from an RCDATA-type resource with the

special name, DLGINCLUDE, to a DLGINCLUDE resource type whose name can

be specified. The dialog editor would look for resources of the type

DLGINCLUDE.

We are being more strict about the need for resources to be unique in the

Win32 SDK than the Windows 3.1 SDK. This is good because there was never

any guarantee at run time as to which of the two or more resources would be

returned by LoadResource().

This means that some applications being ported to Windows NT give an error

when their resources are compiled because they have duplicate RCDATA type

resources with the same name (DLGINCLUDE). This error is by design. The

workaround is straightforward: delete all the DLGINCLUDE RCDATA type

resource statements from all the .DLG files.

Finally, because it does not make sense to have the DLGINCLUDE type

resources in the executable, the linker will strip them out so that they

don't get linked into the EXE.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsDlg


INF: Using the C Run Time

Article ID: Q94248

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

This document contains the following sections:

   Section 1:  Three Forms of C Run-Time (CRT) Library Are Available

   Section 2:  Using the CRT Libraries When Building a DLL

   Section 3:  Using NTWIN32.MAK to Simplify the Build Process

   Section 4:  Problems Encountered When Using Multiple CRT Libraries

   Section 5:  Mixing Library Types

MORE INFORMATION

================

Section 1:  Three Forms of C Run-Time (CRT) Libraries Are Available

-------------------------------------------------------------------

There are three forms of the C Run-time library provided with the Win32

SDK:

 - LIBC.LIB is a statically linked library for single-threaded programs.

 - LIBCMT.LIB is a statically linked library that supports multithreaded

   programs.

 - CRTDLL.LIB is an import library for CRTDLL.DLL that also supports

   multithreaded programs. CRTDLL.DLL itself is part of Windows NT.

Microsoft Visual C++ 32-bit edition contains these three forms as well,

however, the CRT in a DLL is named MSVCRT.LIB. The DLL is redistributable.

Its name depends on the version of VC++ (ie MSVCRT10.DLL). Note however,

that MSVCRT10.DLL is not supported on Win32s, while CRTDLL.LIB is supported

on Win32s.

Section 2: Using the CRT Libraries When Building a DLL

------------------------------------------------------

When building a DLL which uses any of the C Run-time libraries, in order to

ensure that the CRT is properly initialized, either

1. the initialization function must be named DllMain() and the entry point

   must be specified with the linker option -entry:_DllMainCRTStartup@12

   - or -

2. the DLL's entry point must explicitly call CRT_INIT() on process attach

   and process detach

This permits the C Run-time libraries to properly allocate and initialize C

Run-time data when a process or thread is attaching to the DLL, to properly

clean up C Run-time data when a process is detaching from the DLL, and for

global C++ objects in the DLL to be properly constructed and destructed.

The Win32 SDK samples all use the first method. Use them as an example.

Note that DllMainCRTStartup() calls CRT_INIT() and CRT_INIT() will call

your application's DllMain(), if it exists.

If you wish to use the second method and call the CRT initialization code

yourself, there are two techniques:

1. if there is no entry function which performs initialization code, simply

   specify CRT_INIT() as the entry point of the DLL. Assuming that you've

   included NTWIN32.MAK, which defines DLLENTRY as "@12", add the following

   option to the DLL's link line:

      -entry:_CRT_INIT$(DLLENTRY)

   - or -

2. if you *do* have your own DLL entry point, do the following in the entry

   point:

   a. Use this prototype for CRT_INIT():

       BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD fdwReason,

          LPVOID lpReserved);

      For information on CRT_INIT() return values, see the documentation

      DllEntryPoint; the same values are returned.

   b. On DLL_PROCESS_ATTACH and DLL_THREAD_ATTACH (see "DllEntryPoint" in

      the Win32 API reference for more information on these flags), call

      CRT_INIT(), first, before any C Run-time functions are called or any

      floating-point operations are performed.

   c. Call your own process/thread initialization/termination code.

   d. On DLL_PROCESS_DETACH and DLL_THREAD_DETACH, call CRT_INIT() last,

      after all C Run-time functions have been called and all floating-

      point operations are completed.

   Be sure to pass on to CRT_INIT() all of the parameters of the entry

   point; CRT_INIT() expects those parameters, so things may not work

   reliably if they are omitted (in particular, fdwReason is required to

   determine whether process initialization or termination is needed).

   Below is a skeleton sample entry point function that shows when and how

   to make these calls to CRT_INIT() in the DLL entry point:

    BOOL WINAPI DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason,

        LPVOID lpReserved)

    {

    if (fdwReason == DLL_PROCESS_ATTACH || fdwReason == DLL_THREAD_ATTACH)

        if (!_CRT_INIT(hinstDLL, fdwReason, lpReserved))

            return(FALSE);

    if (fdwReason == DLL_PROCESS_DETACH || fdwReason == DLL_THREAD_DETACH)

        if (!_CRT_INIT(hinstDLL, fdwReason, lpReserved))

            return(FALSE);

    return(TRUE);

    }

    NOTE that this is *not* necessary if you are using DllMain() and

    -entry:_DllMainCRTStartup@12.

Section 3: Using NTWIN32.MAK to Simplify the Build Process

----------------------------------------------------------

There are macros defined in NTWIN32.MAK that can be used to simplify your

makefiles and to ensure that they are properly built to avoid conflicts.

For this reason, Microsoft highly recommends using NTWIN32.MAK and the

macros therein.

For compilation, use one of the following:

   $(cvarsdll)          for single-threaded apps/DLLs using CRT in a DLL

   $(cvarsmtdll)        for multithreaded apps/DLLs using CRT in a DLL

For linking, use one of the following:

   $(conlibsdll)        for console apps/DLLs using CRT in a DLL

   $(guilibsdll)        for GUI apps using CRT in a DLL

Section 4: Problems Encountered When Using Multiple CRT Libraries

-----------------------------------------------------------------

If an application that makes C Run-time calls links to a DLL that also

makes C Run-time calls, be aware that if they are both linked with one of

the statically-linked C Run-time libraries (LIBC.LIB or LIBCMT.LIB), the

.EXE and DLL will have separate copies of all C Run-time functions and

global variables. This means that C Run-time data cannot be shared between

the .EXE and the DLL. Some of the problems that can occur as a result are:

 - Passing buffered stream handles from the .EXE/DLL to the other module

 - Allocating memory with a C Run-time call in the .EXE/DLL and

   reallocating or freeing it in the other module

 - Checking or setting the value of the global errno variable in the

   .EXE/DLL and expecting it to be the same in the other module. A related

   problem is calling perror() in the opposite module from where the C Run-

   time error occurred, since perror() uses errno.

To avoid these problems, link both the .EXE and DLL with CRTDLL.LIB or

MSVCRT.LIB, which allows both the .EXE and DLL to use the common set of

functions and data contained within CRT in a DLL, and C Run-time data such

as stream handles can then be shared by both the .EXE and DLL.

Section 5: Mixing Library Types

-------------------------------

You can link your DLL with CRTDLL.LIB/MSVCRT.LIB regardless of what your

.EXE is linked with if you avoid mixing CRT data structures and passing

CRT file handles or CRT FILE* pointers to other modules.

When mixing library types adhere to the following:

 - CRT file handles may only be operated on by the CRT module that created

   them.

 - CRT FILE* pointers may only be operated on by the CRT module that

   created them.

 - Memory allocated with the CRT function malloc() may only be freed or

   reallocated by the CRT module that allocated it.

To illustrate this, consider the following example:

   - .EXE is linked with MSVCRT.LIB

   - DLL A is linked with LIBCMT.LIB

   - DLL B is linked with CRTDLL.LIB

   If the .EXE creates a CRT file handle using _create() or _open(), this

   file handle may only be passed to _lseek(), _read(), _write(), _close(),

   etc. in the .EXE file. Do not pass this CRT file handle to either DLL.

   Do not pass a CRT file handle obtained from either DLL to the other DLL

   or to the .EXE.

   If DLL A allocates a block of memory with malloc(), only DLL A may call

   free(), _expand(), or realloc() to operate on that block. You cannot

   call malloc() from DLL A and try to free that block from the .EXE or

   from DLL B.

   NOTE: If all three modules were linked with CRTDLL.LIB or all three were

   linked with MSVCRT.LIb, these restrictions would not apply.

When linking DLLs with LIBC.LIB, be aware that if there is a possibility

that such a DLL will be called by a multithreaded program, the DLL will

not support multiple threads running in the DLL at the same time, which can

cause major problems. If there is a possibility that the DLL will be called

by multithreaded programs, be sure to link it with one of the libraries

that support multithreaded programs (LIBCMT.LIB, CRTDLL.LIB or MSVCRT.LIB).

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


INF: CTYPE Macros Function Incorrectly

Article ID: Q94323

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

When an application that is linked to CRTDLL.LIB is compiled without

defining _MT and _DLL, the CTYPE.H family of macros will not operate

correctly.

To define _MT and _DLL on the CL386 command line, just add the following to

the command line:

   -D_MT -D_DLL

By adding these defines, the CTYPE macros will be properly initialized.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


INF: Thread Local Storage Overview

Article ID: Q94804

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Thread local storage (TLS) is a method by which each thread in a given

process is given a location(s) in which to store thread-specific data.

Four functions exist for TLS: TlsAlloc(), TlsGetValue(), TlsSetValue(), and

TlsFree(). These functions manipulate TLS indexes, which refer to storage

areas for each thread in a process. A given index is valid only within the

process that allocated it.

Note that the Visual C++ compiler supports an alternate syntax:

   _declspec( thread )

which can be used in place of directly calling these APIs. Please see the

description of _declspec in the VC++ "Language and Run-time Help" helpfile

for more information.

MORE INFORMATION

================

A call to TlsAlloc() returns a global TLS index. This one TLS index is

valid for every thread within the process that allocated it, and should

therefore be saved in a global or static variable.

Thread local storage works as follows: when TlsAlloc() is called, every

thread within the process has its own private DWORD-sized space reserved

for it (in its stack space, but this is implementation-specific). However,

only one TLS index is returned. This single TLS index may be used by each

and every thread in the process to refer to the unique space that

TlsAlloc() reserved for it.

For this reason, TlsAlloc() is often called only once. This is convenient

for DLLs, which can distinguish between DLL_PROCESS_ATTACH (where the first

process's thread is connecting to the DLL) and DLL_THREAD_ATTACH

(subsequent threads of that process are attaching). For instance, the first

thread calls TlsAlloc() and stores the TLS index in a global or static

variable, and every other thread that attaches to the DLL refers to the

global variable to access their local storage space.

Although one TLS index is usually sufficient, a process may have up to

TLS_MINIMUM_AVAILABLE indexes (guaranteed to be greater than or equal

to 64).

Once a TLS index has been allocated (and stored), the threads within the

process may use it to set and retrieve values in their storage spaces. A

thread may store any DWORD-sized value in its local storage (for example, a

DWORD value, a pointer to some dynamically allocated memory, and so forth).

The TlsSetValue() and TlsGetValue() APIs are used for this purpose.

A process should free TLS indexes with TlsFree() when it has finished using

them. However, if any threads in the process have stored a pointer to

dynamically allocated memory within their local storage spaces, it is

important to free the memory or retrieve the pointer to it before freeing

the TLS index, or it will be lost.

For more information, please see "Using Thread Local Storage" in the

"Processes and Threads" overview in the "Win32 Programmer's Reference".

Example

-------

Thread A within a process calls TlsAlloc(), and stores the index returned

in the global variable TlsIndex:

   TlsIndex = TlsAlloc();

Thread A then allocates 100 bytes of dynamic memory, and stores it in its

local storage:

   TlsSetValue( TlsIndex, malloc(100) );

Thread A creates thread B, which stores a handle to a window in its local

storage space referred to by TlsIndex.

   TlsSetValue( TlsIndex, (LPVOID)hSomeWindow );

Note that TlsIndex refers to a different location when thread B uses it,

than when thread A uses it. Each thread has its own location referred to by

the same value in TlsIndex.

Thread B may terminate safely because it does not need to specifically free

the value in its local storage.

Before thread A terminates, however, it must first free the dynamically

allocated memory in its local storage

   free( TlsGetValue( TlsIndex ) );

and then free the TLS index:

   if ( !TlsFree( TlsIndex ) )

      // TlsFree() failed.  Handle error.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseProcThrd


INF: Postmortem Debugging Under Windows NT

Article ID: Q94924

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The Win32 Software Development Kit (SDK) does not have a postmortem utility

designed to ship with the product. However, the system provides fundamental

support to enable postmortem analysis of processes and allows tool vendors

to create their own postmortem solutions.

A key feature provided in the system is the ability to start up a debugger

when an unhandled exception occurs. The debugger can attach to the process

after the exception has occurred.

MORE INFORMATION

================

In the first commercial release of Windows NT, a 32-bit version of Dr.

Watson is automatically run as a postmortem debugger when unhandled

exceptions occur. The Dr. Watson log obtained from application end-users

can be useful to the developers of the application in determining the cause

of failure.

When the Win32 SDK is installed, the default postmortem debugger is changed

to be WinDbg, so on the machines developers use to develop/test their

applications under development, the developer is immediately given a WinDbg

session to investigate the cause of failure when an unhandled exception

occurs.

The option also allows administrators to configure systems such that any

third-party utility or utility written in-house could be started. The

utility is exec'd with debugger/debugee relationship. The process address

space is retained and the debugger is set at the instruction causing the

unhandled exception.

Thus, this interface is not limited to debuggers, but to any postmortem

utility. Therefore, there is an opportunity for tool vendors to provide a

myriad of postmortem analysis utilities, some of which could be tied to

compiler vendor products (for symbolic dumps and so forth).

A postmortem utility could:

1. Dump memory image to disk for later analysis.

2. View/dump memory structures, memory maps, and so forth via

   VirtualQuery().

3. Study/dump the CPU state, coprocessor state, and so forth.

4. Take advantage of any application symbolic debugging information if

   present.

There are many other aspects to a postmortem utility that could be added.

Core dumps have additional features (such as system support for reloading)

that will not be provided in the Windows NT final release for this version,

but are being planned for a future release.

Additional reference words: 3.10 post-mortem

KBCategory: Prg

KBSubcategory: TlsMisc


INF: Size Comparison of 32-Bit and 16-Bit x86 Applications

Article ID: Q97765

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

It is expected that a 32-bit version of an x86 application (console or GUI)

will be larger than the 16-bit version. Much of this difference is due to

the flat memory-model addressing of Windows NT. For each instruction, note

that the opcodes have not changed in size, but the addresses have been

widened to 32 bits.

In addition, the EXE format under Windows NT (the PE format) is optimized

for paging; EXEs are demand-loaded and totally mappable. This leads to some

internal fragmentation because protection boundaries must fall on sector

boundaries within the EXE file.

The MIPS (or any RISC) version of a Win32 application typically will be

larger and require more memory than its x86 counterpart.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


INF: CTRL+C Exception Handling Under WinDbg

Article ID: Q97858

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

An exception is raised for CTRL+C only if the process is being debugged.

The purpose is to make it convenient for the debugger to catch CTRL+C in

console applications. For the purposes of this article, the debugger is

assumed to be WinDbg.

MORE INFORMATION

================

When the console server detects a CTRL+C, it uses CreateRemoteThread() to

create a thread in the client process to handle the event. This new thread

then raises an exception IF AND ONLY IF the process is being debugged. At

this point, the debugger either handles the exception or it continues the

exception unhandled.

The "gh" command marks the exception as having been handled and continues

the execution. The application does not notice the CTRL+C, with one

exception: CTRL+C causes alertable waits to terminate. This is most

noticable when executing:

   while( (c = getchar()) != EOF )  - or -  while( gets(s) )

It is not possible to get the debugger to stop the wait from terminating.

The "gn" command marks an exception as unhandled and continues the

execution. The handler list for the application is searched, as documented

for SetConsoleCtrlHandler(). The handler is executed in the thread created

by the console server.

After the exception is handled, the thread created to handle the event

terminates. The debugger will not continue to execute the application if Go

On Thread Termination is not enabled (from the Options menu, choose Debug,

and select the Go On Thread Termination check box). The thread and process

status indicate that the application is stopped at a debug event. As soon

as the debugger is given a go command, the dead thread disappears and the

application continues execution.

There are three cases where CTRL+C doesn't cause the program to stop

executing (instead it causes a "page down"):

1. When CTRL+C is already being handled.

2. When the debugger is in the foreground and a source window has the

   focus (both must be true).

3. When the CTRL+C exception is disabled (through the Debugger

   Exceptions dialog box).

This follows the convention of the WordStar/Turbo C/Turbo Pascal editor

commands.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


INF: Debugging DLLs Using WinDbg

Article ID: Q97908

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

This article describes the process of debugging dynamic-link libraries

(DLLs) under WinDbg. As a further example, debugging File Manager

extensions is discussed in the "More Information" section in this article.

MORE INFORMATION

================

The application and the DLL must be built with certain compiler and linker

switches so that debugging information is included. These switches can be

found in the $(cdebug) and $(ldebug) macros, respectively, which are

defined in NTWIN32.MAK.

NOTE: It is important to disable optimization with -Od or locals will not

be available in the locals window and line numbers may not match the

source.

The application is loaded into WinDbg either by specifying "windbg

<filename>" on the command prompt or by starting WinDbg from the program

group and specifying <filename> in the Program Open dialog box (from the

Program menu, choose Open). Note that <filename> is the name of the

application, not the DLL. It is not necessary to specify the name of the

DLL to be debugged.

The DLL is loaded either when execution of the application begins or

dynamically through a call to LoadLibrary(). In the first case, simply

press F8 to begin execution. All DLLs and symbolic information are loaded.

To trace through the DLL code, breakpoints can be set in the DLL using a

variety of methods:

 - From the Debug menu, choose Breakpoints. The dialog box is Program Open.

   -or-

 - Open the source file and use F9 or the "hand" button on the toolbar.

   -or-

 - Go to the Command window and type:

       bp[#] <Options>

   <Options>:

      addr          break at address

      @line         break at line

In the case that the DLL is dynamically loaded, pressing F8 causes all

other DLLs and symbolic information to load. The same methods described

above can be used to set breakpoints; however, the user will get a dialog

box indicating that the breakpoint was not instantiated. After the call to

LoadLibrary() has been executed, all breakpoints are instantiated (it is

possible to note the color change if the DLL source window is open) and

will behave as expected.

To set a breakpoint in a DLL that is not loaded, specify the context when

setting the breakpoint. The syntax for a context specifier is:

   {proc, module, exe}addr

   -or-

   {proc, module, exe}@line

Example: {func, module.c, app.exe}0x50987. The first two parameters are

optional, so {,,app.exe}0x50987 or {,,app.exe}func could be used instead.

For example, assume that we are trying to debug a File Manager extension

that has been built with full debugging information. The procedure to debug

the extension is as follows:

1. Open a Command window.

2. Start WinDbg WINFILE.

3. Set a breakpoint on FmExtensionProc().

4. At the Command window, type "g" and press ENTER. The debugger will

   continue executing the program form the point where it stopped

   (which could be from the beginning, at the breakpoint, and so on).

WinDbg will start WINFILE and when FmExtensionProc() is executed, WinDbg

will break into the WINFILE process.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


INF: Language ID Needed for RC.EXE

Article ID: Q97924

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The RC command-line switch -l is used to specify the default language

ID for resources. For example

   rc -l 409

would specify a language of US English.

If you do not set the -l switch when you build, you may see the following

error message:

   The specified resource language ID cannot be found in the image

   file.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsRc


INF: Watching Local Variables That Are Also Globally Declared

Article ID: Q98288

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Consider debugging the following program in WinDbg:

   int x = 1;

   int y = 2;

   void main()

   {

      int x = 2;

      x++;

      y++;

   }

Before you step into main, if you set watchpoints on x and y, the

Watch window will display a value for y but for x will say "Expression

cannot be evaluated." To see the value for x, use ::x and x will

evaluate to the local x in main once you've stepped into main.

MORE INFORMATION

================

When debugging an application, the X86 C++ evaluator is loaded. Given

this, you can use the scope resolution operator in a watch statement

to view a hidden global variable. Without the use of the scope

resolution operator, there is no way (short of watching it in a memory

window) to watch a hidden global variable.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


INF: Determining Memory Usage Under Windows NT

Article ID: Q98721

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The following are tools available in Windows NT that can help you

determine memory usage in your system:

PMON - Allows you look at all the processes on the system, and monitor

their memory usage and private commitment. This tool is

character-mode-based and updates every 5 seconds.

PVIEW - Provides information at an individual process's address space

and memory usage. This function provides more detail than PMON.

PWALK - A GUI tool allowing you to examine the address space of your

application or another running .EXE. See the Process Walker icon in

the Win32 SDK group in Program Manager. Process Walker provides more

detail than PVIEW.

MORE INFORMATION

================

The easiest way for you to determine your memory usage is to run PMON.

Here's a sample output screen from PMON:

 Process Monitor: Total Memory:  16192Kb Availble    4348Kb PgFlts:38

   Commit:   31692Kb /  19500Kb Limit:   40028Kb  Pool: 1508Kb /2044Kb

                 Mem   Mem    Page   Flts Commit Thd Image

%CPU  CPU Time Usage  Diff    Faults Diff Charge Cnt  Name

                 896     0   2201408    0             File Cache

 82  10:21:10     16     0         0    0      0   1  Idle Process

  0   0:23:52     16     0       771    0     32  20  System Process

  0   0:00:00      0     0       106    0    192   6  smss.exe

  6   0:54:15   2140     0     55528    0   3832  29  csrss.exe

  0   0:00:01      0     0       550    0    456   2  winlogon.exe

  0   0:00:06      0     0      2044    0    952   4  screg.exe

  0   0:00:07      0     0      8153    0    592   8  lsass.exe

  0   0:00:25      0     0      6185    0    640   4  spoolss.exe

  0   0:00:00      0     0      1193    0    348   5  EventLog.exe

  0   0:00:00      0     0       245    0    332   2  mcsxnsvc.exe

  0   0:00:08      0     0      8830    0    264   2  ubnbsvc.exe

  0   0:00:00      0     0       713    0    552   7  netdde.exe

  0   0:00:01     16     0         7    0      4   8  No Name Found

  0   0:00:00      0     0       495    0    316   2  clipsrv.exe

  0   0:00:20    120     0     16892    0    652  12  lmsvcs.exe

  0   0:00:00      0     0       763    0    484   7  MsgSvc.exe

  0   0:00:00      0     0       450    0    296   1  nddeagnt.exe

  0   0:00:01      0     0       926    0    240   1  taskman.exe

  0   0:00:03    348     0      1805    0    324   2  progman.exe

  0   0:00:31      0     0      5784    0    224   1  CMD.exe

  0   0:00:50    156     0     13712    0    120   1  PERFMTR.EXE

  0   0:00:03      0     0       912    0    144   1  CMD.exe

  0   0:01:15     20     0      5379    0   4052   4  ntvdm.exe

  0   0:00:03      0     0      1352    0    156   1  CMD.exe

  0   0:15:28    308     0     43509    0    280   1  PMON.EXE

  0   0:00:47    252     0     16776    0   1828   2  I386KD.EXE

  2   0:05:17   2652     0      3056    0    900   3  MSMAIL32.EXE

  0   0:01:07    224     0     23298    0    600   3  MAILSP32.EXE

  0   0:00:00     20     0       199    0    328   1  STATUS.EXE

  7   0:00:14   1060     0      1529   38    360   1  slm.exe

The first line indicates that the current machine has 16 megabytes

(MB) of memory, of which 4348K is unused, and there have been 38 page

faults since the last update.

The second line indicates that the total commitment is 31692K with the

private commitment at 19500K. Private commits are writable pages that

are not shared; they are private to that process, usually created with

LocalAlloc() or VirtualAlloc(). The difference between these two

numbers, in this case 12196K, is the amount of memory used by pagable

drivers, paged pool, and page-file-backed shared memory regions.

Drivers have about 1 MB of pagable memory, and the system we are

examining has about 2 MB of paged pool; therefore, subtracting 3 MB

from the 12 MB of other commitment, yields 9 MB of shared virtual

memory.

The total commit limit is 40028K. Nonpaged pool is using 1508K; paged

pool is using 2044K.

The rest of the screen describes the memory consumption on a

process-by-process basis. The Mem Usage column is the amount of

physical memory in kilobytes that application is using. If it is 0,

the application has been entirely paged out of memory. The Mem Diff

column is the difference in memory usage in kilobytes over the last 5

seconds. The other column of interest is the Commit Charge. This is

the total number of writable nonshared pages in the process.

From a quick scan of the list, the Windows subsystem CSRSS.EXE is

consuming just over 2 MB with almost 4 MB committed. MSMAIL32 is

consuming around 2.5 MB with 3 MB committed. NTVDM is consuming 20K

with 4 MB committed.

The larger these numbers are, the poorer the system performance. CSRSS

generally is between 2 and 3 MB with 3 to 4 MB committed. The more

memory you have, the more memory an application is given. Therefore,

if you have 2 MB, CSRSS will consume about 5 MB. If your system seems

to be sluggish and PMON shows numbers that seem excessive, you should

check for memory leaks. Memory leaks happen when certain commands are

executing over and over causing huge commitments in certain processes.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


FIX: Global Constructors Not Called in Alpha DLLs

Article ID: Q98732

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

C++ constructors on global variables are not invoked when a dynamic link

library (DLL) is loaded on the Alpha AXP platform.

STATUS

======

Microsoft has confirmed this to be a problem in Windows NT and Windows NT

Advanced Server version 3.1. This problem was corrected in the latest U.S.

Service Pack for Windows NT and Windows NT Advanced Server version 3.1. For

information on obtaining the Service Pack, query on the following word in

the Microsoft Knowledge Base (without the spaces):

   S E R V P A C K

Additional reference words: 3.10

KBCategory: Prg

KBSubCategory: TlsMisc


PRB: MS-SETUP Uses \SYSTEM Rather Than \SYSTEM32

Article ID: Q98888

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

Call GetWindowsSysDir() in the SETUP.MST file of a 16-bit setup

application. The return value is C:\WINNT\SYSTEM\ instead of

C:\WINNT\SYSTEM32\. Note that this doesn't happen with the 32-bit Setup

Toolkit.

CAUSE

=====

Windows on Win32 (WOW) returns the SYSTEM directory, not the SYSTEM32

directory, to 16-bit applications such as MS-SETUP. This is done for

compatibility reasons.

RESOLUTION

==========

Determine whether the setup code is being run under WOW or Windows version

3.1 by checking the WF_WINNT bit (0x4000) in the return from GetWinFlags().

Choose either the return from GetWindowsSysDir() or <winows dir>\system32

as appropriate.

MORE INFORMATION

================

Note that there are additional considerations for network installs for

Win32s, because the SYSTEM directory may not be a branch off of the Windows

directory.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMss


INF: Debugging a Service with WinDbg

Article ID: Q98890

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The following steps illustrate how to debug a service under Windows NT

using WinDbg, which ships with the Win32 Software Development Kit (SDK).

For illustration purposes, this procedure uses the SERVICE sample

(\MSTOOLS\SAMPLES\SERVICE), which is built with debugging information by

default.

MORE INFORMATION

================

1. Install the Simple service with the following command:

      instsrv simple <drive>:\mstools\samples\service\simple.exe

   Upon success, you will receive the message "CreateService Success".

2. Use the Control Panel's Services application to start the Simple

   service.

3. Use PView to get the process ID (PID) for the Simple service. For

   instance, if PView shows the process as simple(0xD5), then the PID

   is 0xD5.

4. Convert the PID from hexadecimal to decimal. For example, 0xD5 is 213

   in decimal.

5. At a command prompt, go to <DRIVE>:\MSTOOLS\SAMPLES\SERVICE and type

      start windbg

   to start WinDbg in its own command shell.

6. In WinDbg, choose Open from the File menu and open the source file

   (SIMPLE.C).

7. Set breakpoints at (for example) lines 326, 335, 337, 344, and 353.

   The lines will not change color at this point, but the breakpoints

   are successfully set.

8. Open a command window in WinDbg and type

      .attach <PID>

   where <PID> is a decimal number obtained in steps 4 and 5. The

   .attach command does not accept hexadecimal numbers.

   Note that the lines where breakpoints are set will have changed

   colors.

9. Type "g" (a go command) in the WinDbg command window to restart

   after the thread that WinDbg uses to do the .attach terminates.

10. At a command prompt, go to <DRIVE>:\MSTOOLS\SAMPLES\SERVICE and

    type

       client \\.\pipe\simple boo

11. Press F5 (a go command) to debug the service. The breakpoint hit

    will be on line 335. Press F5 again to go to the next breakpoint.

    Keep pressing F5 until line 326 waits again for a client to

    connect. Try connecting another client and repeat the same steps.

Exiting WinDbg will kill the service, which must be restarted manually

with the Control Panel.

Note that the service must log on as LocalSystem for this to work

correctly; otherwise, you will not have permission to debug the

service.

The manual translation of the PID from hexadecimal to decimal will not

be needed in the future once the .attach command is modified so that

it accepts hexadecimal.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


PRB: Cannot Compile from Win32 SDK M Editor (MEP.EXE)

Article ID: Q98918

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The Win32 Software Development Kit (SDK) M Editor compile function uses the

correct extmake line and spawns the compiler correctly, but does not

produce the desired result. The terminating beep is issued, but no messages

appear in the <compile> pseudo file and no object file is produced.

STATUS

======

Microsoft has confirmed this to be a problem in the Win32 SDK Microsoft

Editor.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMep


INF: Source-level Debugging Under NTSD

Article ID: Q99053

------------------------------------------------------------------------

The information in this article applies to:

   - Microsoft Win32 Software Development Kit (SDK) for Windows NT

     version 3.10

------------------------------------------------------------------------

The following are the steps used for source-level debugging under NTSD:

1. Compile using -Zi and -Od.

2. Link using debug:full and debugtype:coff.

3. Load the program into the debugger.

4. Use s+ to change to source mode.

   -or-

   Use s& to change to mixed mode.

For a console application, type "g main" to get to the program start. For a

GUI application, type "g WinMain" to get to the program start.

Type "v .<number>" to list source lines starting at <number>. For example,

type the following

   v .20

to see all lines starting at line 20.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


INF: Compile Errors Caused by Missing Option -D_X86_

Article ID: Q99516

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

When compiling Win32 applications on an Intel x86 system, the following

errors are generated if the symbol _X86_ is not defined:

   C:\MSTOOLS\h\winnt.h(1235) : error C2061: syntax error : identifier

      'PCONTEXT'

   C:\MSTOOLS\h\winnt.h(1236) : error C2143: syntax error : missing ';'

      before '}'

   C:\MSTOOLS\h\winbase.h(615) : error C2282: 'PCONTEXT' is followed by

      'LPCONTEXT' (missing ','?)

   C:\MSTOOLS\h\winbase.h(617) : error C2282: 'PEXCEPTION_POINTERS' is

      followed by 'LPEXCEPTION_POINTERS' (missing ','?)

   C:\MSTOOLS\h\winbase.h(1409) : error C2061: syntax error : identifier

      'lpContext'

   C:\MSTOOLS\h\winbase.h(1416) : error C2059: syntax error : '*'

   C:\MSTOOLS\h\winbase.h(1416) : error C2061: syntax error : identifier

      'lpContext

MORE INFORMATION

================

Certain sections of WINNT.H and WINBASE.H are conditionally compiled

with:

   #ifdef _X86_

Therefore, failing to compile with the -D_X86_ switch causes these errors

to occur.

For recommendations regarding which compile and link options to use, check

the makefiles included with the samples. These makefiles use the macros

defined (and described) in \MSTOOLS\H\NTWIN32.MAK.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


PRB: Debugging the Open Common Dialog Box in WinDbg

Article ID: Q99952

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

When debugging an application that uses the Open common dialog box (created

by the GetOpenFileName() function) in WinDbg, the program stops and the

following information is displayed in the Command window:

   Thread Terminate: Process=0, Thread=2, Exit Code=1

CAUSE

=====

The Open common dialog box causes a thread to be created. At this point in

the debugging, that thread has terminated. By default, WinDbg halts

whenever a thread terminates.

RESOLUTION

==========

Execute the go command (type "g" at the command prompt). Execution will

continue.

MORE INFORMATION

================

To prevent WinDbg from halting when a thread is terminated, select Debug

from the Options menu and check "Go on thread terminate."

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


INF: WinDbg Message "Breakpoint Not Instantiated"

Article ID: Q99953

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

The WinDbg message "Breakpoint Not Instantiated" indicates that the

debugger could not resolve an address. This can happen for several reasons:

 - A specified symbol does not exist. In this case, check for

   misspelling and check the state of the "ignore case" option if the

   symbol contains mixed case.

   -or-

 - The symbol exists, but the EXE or DLL was built with the wrong

   debugging information, or none at all. Use the -Zi and -Od compiler

   options and use the -debug:full and -debugtype:cv linker options.

   -or-

 - The symbol exists, but it is in a module that has not yet been

   loaded. If the symbol is in a DLL that is dynamically loaded the

   breakpoint was probably set before the DLL was loaded. The message

   is harmless, because WinDbg will instantiated the BP when the module

   is loaded.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


INF: Enabling Disk Performance Counters

Article ID: Q100289

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

By default, disk performance counters are not started. Therefore, almost

all of the disk metrics obtained will be zero. To enable the disk

performance counters, execute the following command and then reboot the

system:

   diskperf -y

DISKPERF.EXE is located in %SystemRoot%\system32.

The decision to avoid starting disk performance counters by default was

made for performance reasons.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


PRB: Data Section Names Limited to Eight Characters

Article ID: Q100292

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

Data sections can be named by using #pragma data_seg. This method is

commonly used so that the named data sections can be shared using the

SECTIONS statement in the DEF file. However, if the length of the name

specified in the pragma exceeds eight characters, then the section is not

properly shared.

CAUSE

=====

The compiler truncates the section name length to eight characters because

the linker does not support sections with longer names. Therefore, the

names specified in the DEF file do not resolve to actual section names.

STATUS

======

The longer names require use of the COFF strings table, so the rewrite is

not trivial. When the linker in a future Microsoft C/C++ product supports

this, then the compiler will as well.

MORE INFORMATION

================

Note that in addition, the first character of a section name must be a

period. Therefore, the section name, as specified in both the pragma and

the DEF file, can be a maximum of a period followed by seven characters.

For more information on the shared named-data section, query on the

following words in the Microsoft Knowledge Base:

   specify and shared and nonshared and data and dll

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


INF: Setting Dynamic Breakpoints in WinDbg

Article ID: Q100642

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The WinDbg breakpoint command contains a metacircular interpreter; that is,

you can execute commands dynamically once a breakpoint is hit. This allows

you to perform complex operations, including breaking when an automatic

variable has changed, as described below.

The command interpreter of WinDbg allows any valid C expression to serve as

a break condition. For example, to break whenever a static variable has

changed, use the following expression in the Expression field of the

breakpoint dialog box:

   &<variablename>

In addition, the length should be specified as 4 (the size of a DWORD) in

the length field.

This technique does not work for automatic variables because the address of

an automatic variable may change depending on the value that the stack

pointer has upon entering the function that defines the automatic variable.

This is one case where the breakpoint needs to be redefined dynamically.

For this purpose, a breakpoint can be enabled at function start and

disabled at function exit, so that the address of the variable is

recomputed.

MORE INFORMATION

================

Suppose that the name of the function is "subroutine" and the local

variable name is "i". The following steps will be used:

1. Start the program and step into the function that defines the

   automatic variable with the commands:

      g subroutine

      p

      bp500 ={subroutine}&i /r4 /C"?i"

   The breakpoint number is chosen to be large so that the breakpoint

   will be well out of range of other breakpoints. Note that /r4

   indicates a length of 4 because i is an integer. Make this number

   larger for other data types. The command "?i" prints out the value

   of i.

2. Next, disable this first breakpoint with the command

      bd500

   because the address of i may change. The breakpoint will be enabled

   when in the scope of function subroutine.

3. The second breakpoint definition is set at the entry point of the

   function:

      bp .<FirstLine> /C"be 500;g"

   This is where the breakpoint is enabled. Note that <FirstLine> is

   the line number of the first statement in the function subroutine.

4. The last breakpoint is set at the end of the function

      bp .<LastLine> /C"bd 500;g"

   and will disable the breakpoint again. Note that <LastLine> is the

   line number of the last statement in the function subroutine.

   Note that if the function has more than one exit point, multiple

   breakpoints may have to be defined.

Program execution stops when breakpoint #500 is hit (for example, the value

of i changes), but execution will continue after the other two breakpoints

because they contain go ("g") commands.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


PRB: Debugging an Application Driven by MS-TEST

Article ID: Q100957

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

When an application driven by MS-TEST is being debugged by WinDbg or NTSD

(for example, after an exception has occurred), both the application and

the debugger hang.

CAUSE

=====

The debugger is hooked and ends up hanging.

RESOLUTION

==========

It is not possible to use NTSD or WinDbg to debug an application that is

driven by MS-TEST. Use Dr. Watson (drwtsn32) instead. Note that you must

turn off Visual Notification.

STATUS

======

Microsoft has confirmed this to be a problem in Windows NT version 3.1. We

are researching this problem and will post new information here in the

Microsoft Knowledge Base as it becomes available.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


INF: Interpreting Executable Base Addresses

Article ID: Q101187

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

LINK.EXE and DUMPBIN.EXE (from Visual C++ 32-bit edition) can be used to

dump the portable executable (PE) header of an executable file. Below is a

fragment of a dump:

   7300 address of entry point

   7000 base of code

   B000 base of data

        ----- new -----

   10000 image base

The "image base" value of 10000 is the address where the program begins in

memory. The value associated with "base of code," "base of data," and

"address of entry point" are all offsets from the image base.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


INF: Debugging Console Apps Using Redirection

Article ID: Q102351

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

To redirect the standard input (STDIN) for a console application named

APP.EXE from a file named INPUT.TXT, the following syntax is used:

   app < input.txt

However, the following syntax will not work when attempting to debug

this application using WinDbg with STDIN redirected:

   windbg app < input.txt

To debug the application as desired, use

   windbg cmd /c "app < input.txt"

MORE INFORMATION

================

This will allow WinDbg to debug whatever goes on in the cmd window. A

dialog box will be displayed that says "No symbolic Info for Debuggee."

This message refers to CMD.EXE; dismiss this dialog box. When the child

process (APP.EXE) is started, the command window will read "Stopped at

program entry point." To continue, type "g" at the command window. Note

that APP.EXE will begin executing, then you can open the source file and

set breakpoints.

This technique is also useful when debugging an application that behaves

differently when run with a debugger than it does when it is run in the

command window.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


PRB: MIPS Compiler Assertion with C version 8.0

Article ID: Q102764

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

You may get the following assertion from the C version 8.0 compiler on

Windows NT under MIPS:

   Microsoft (R) C Centaur Optimizing Compiler Version 8.00.081

   Copyright (c) Microsoft Corp 1984-1992. All rights reserved.

   t516a.cxx

   Assertion failed: prld->symbol->symbolnumber >= 0, file

   E:\src\centaur\drop81\msas\as1coff.c, line 459

   abnormal program termination

CAUSE

=====

You can get an assertion running C 8.0 on Windows NT MIPS if you did not

compile with /Zi or /Z7 or if your external declarations are not at file

scope level (that is, declare them as global).

RESOLUTION

==========

The easiest workaround is to recompile with /Zi or /Z7. Another workaround

is to move all extern declarations to file scope level.

STATUS

======

There is a fix for this but the problem wasn't deemed critical enough to

change right before the Windows NT 3.1 release.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


INF: Example of Importing Functions

Article ID: Q103244

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

NOTE: This article deals specifically with the Linker shipped with the

Win32 SDK, which is the current linker for MIPS and Alpha only.

The linker does not take a .DEF file directly. To use EXPORTS, it is

standard to build an export module (.EXP) to link with the dynamic-link

library (DLL), and to use an import library (.LIB) to link with any

application or DLL that uses this DLL.

There are alternatives to an import library. One alternative is to use

LoadLibrary() and GetProcAddress() to call an exported DLL function.

Another alternative is to build an import module (.IMP) using the steps

described below:

1. Create the .DEF file. The following is based on the SELECT example.

   Note that it is necessary to decorate the names and include one

   dummy export. The __stdcall functions have an appended "@<number>",

   where <number> is the number of bytes in the parameter list for the

   function. The linker automatically handles the underscore, which is

   prepended to __cdecl and __stdcall function names.

      NAME         Demo

      EXPORTS

         DemoWndProc@12

      IMPORTS

         select.StartSelection@16

         select.UpdateSelection@16

         select.EndSelection@8

         select.ClearSelection@12

2. Build the .IMP file:

      $(PROJ).imp: $(PROJ).def

         $(implib) -machine:$(CPU)   \

         -def:$(PROJ).def            \

         -out:$(PROJ).lib

3. Link the .IMP file into the application:

      $(PROJ).exe: $(PROJ).obj $(PROJ).rbj $(PROJ).def $(PROJ).imp

         $(link) $(linkdebug) $(guiflags)          \

         -out:$(PROJ).exe $(PROJ).obj $(PROJ).rbj  \

         $(PROJ).imp $(guilibsdll)

MORE INFORMATION

================

If building a DLL, another interesting technique is to use forwarders.

For example, the following

   LIBRARY test

   EXPORTS

      MyFunc = prvtdll.DllFunc

will expose MyFunc() as an export for TEST.DLL. However, the loader

will actually fix up the reference at load time to point to DllFunc in

PRVTDLL.DLL. This method involves no additional code.

Another way to provide a forwarder is to write a stub function, which you

do export, that forwards the reference for you. On DLL PROCESS_ATTACH, do

LoadLibrary(prvtdll), then GetProcAddress() on DllFunc. In your forwarder

function, just call through with the arguments passed to you.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


INF: Choosing the Debugger That the System Will Spawn

Article ID: Q103861

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

With Windows NT version 3.1, it is possible to have the system spawn a

debugger whenever an application faults. The capability is controlled

by the following Registry key:

   HKEY_LOCAL_MACHINE\

             SOFTWARE\

            Microsoft\

           Windows NT\

       CurrentVersion\

              AeDebug

This key contains the following values:

   Auto

   Debugger

If the value of Auto is set to "0" (zero), then the system will

generate a pop-up window, and if the user chooses Cancel, spawn the

debugger that is specified in the Debugger value. If the value of Auto

is set to "1", then the system will automatically spawn the debugger

that is specified in the Debugger value.

After installing Windows NT 3.1, the Debugger value is set to DRWTSN32

-p %ld -e %ld -g and the Auto value is set to 1.

If the Win32 SDK is installed, then the Debugger value is changed to

<MSTOOLS>\BIN\WINDBG -p %ld -e %ld and the Auto value is set to 0.

MORE INFORMATION

================

The DRWTSN32 debugger is new and is a post-mortem debugger similar in

functionality to the Windows 3.1 Dr. Watson program. DRWTSN32 generates a

log file containing fault information about the offending application. The

following data is generated in the DRWTSN32.LOG file:

 - Exception information (exception number and name)

 - System information (machine name, user name, OS version, and so forth

 - Task list

 - State dump for each thread (register dump, disassembly, stack walk,

   symbol table)

A record of each application error is recorded in the application event

log. The application error data for each crash is stored in a log file

named DRWTSN32.LOG, which by default is placed in your Windows directory.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


INF: Cannot Load <exe> Because NTVDM Is Already Running

Article ID: Q103863

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

WinDbg can debug 16-bit applications running on Windows NT, under the Win16

VDM (virtual DOS machine), NTVDM.

It is a requirement that NTVDM cannot already be running, and therefore

when debugging a 16-bit application, no other 16-bit applications can be

running. If NTVDM is running, you will get the following error message:

   Cannot load <exe> because NTVDM is already running

To terminate NTVDM, run PView, select NTVDM, and choose "Kill Process."

Note that there may be two NTVDM processes. The one that you want to

terminate has one thread for each Win16 application (plus a few more).

The Windows NT WinLogon is set up to automatically start WoWExec, which

automatically starts the Win16 VDM. This behavior can be changed by

removing WoWExec from:

   HKEY_LOCAL_MACHINE\

             Software\

            Microsoft\

           Windows NT\

       CurrentVersion\

             Winlogon\

                Shell

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


INF: Viewing Globals Out of Context in WinDbg

Article ID: Q105583

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

When viewing global variables (either with the ? command or via the Watch

window) and the variables go out of context, their values become:

   CXX0017 Error: symbol not found

An example of this is when a common dialog box is open in the application.

If you break into an application that is inside COMDLG32.DLL and try to do

a ?gVar, where gVar is a global variable in the application, WinDbg will

not find the symbol because the context is wrong. To view the value of gVar

in MYAPP, use the following:

   ?{,,myapp}gVar

WinDbg will then have no trouble locating the symbolic information.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


PRB: RC Does Not Support __DATE__ or __TIME__

Article ID: Q105584

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The resource compiler (RC) included with the Win32 Software Development Kit

(SDK) does not support the predefined symbols __DATE__ or __TIME__.

Previous versions of the resource compiler accepted these symbols.

CAUSE

=====

It is not intended that the resource compiler support these symbols.

Previous versions of RC used the C/C++ 7.0 preprocessor, which supported

these symbols.

RESOLUTION

==========

If code that uses this symbol is in a header file, place the following

around the individual statements that use them:

   #ifdef RC_INVOKED

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsRc


PRB: Unable to Freeze One Thread in WinDbg

Article ID: Q105585

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The Notes section of the "Set thread" entry of the WinDbg Help file states:

   In any of the above listed states, a thread may be frozen. If a

   thread is at a breakpoint, no threads in that process will run. If

   a thread is at a breakpoint and then frozen, it will still be

   considered stopped until the thread is continued (at which time it

   will still be considered frozen).

If you set a breakpoint in a multithreaded application and freeze a thread

after the breakpoint is hit, all threads stop, as expected. If you then

choose GO on the frozen thread, the message in the Command window is

"Thread is still frozen," which seems fine but all other threads remain

blocked until the thread is unfrozen.

CAUSE

=====

The implementation of ContinueDebugEvent() uses the thread that is being

continued to do some of its work. If the thread is suspended, it cannot

run; therefore, the ContinueDebugEvent operation is not finished until the

thread is resumed.

STATUS

======

Microsoft has confirmed this to be a limitation in WinDbg.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


PRB: WinDbg FIND Dialog Box Slows Down the System

Article ID: Q105586

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

Leaving the WinDbg FIND dialog box displayed after searching for some

string causes the CPU to go to 100 percent busy, making the system very

slow.

RESOLUTION

==========

Choosing Cancel in the FIND dialog box allows the system to return to

normal.

STATUS

======

Microsoft has confirmed this to be a problem in WinDbg.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


INF: Debugging the Win32 Subsystem

Article ID: Q105677

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The instructions on page 1-18 of Part II of the Win32 "Programmer's Guide"

included with the Win32 Device Driver Kit (DDK) says to use NTSD -d -p -1

to attach to the Win32 subsystem process and enable debugging of its user-

mode drivers. This results in the error:

   NTSD: cannot debug PID -1

   error = 5

To enable this procedure to work properly, change the GlobalFlag value

under:

   HKEY_LOCAL_MACHINE\

               SYSTEM\

    CurrentControlSet\

              Control\

      Session Manager

Remove the flag 0x00080000 from 0x211a0000 to make it 0x21120000. The

0x00080000 flag disables the ability to debug CSRSS.EXE (the client

server run time subsystem), which is specified by the "-p -1"

parameter.

It is also possible to debug CSRSS using "WinDbgRm -c -p-1" instead of

NTSD. Make sure that WinDbgRm defaults to debugging using TLPIPE.DLL

as its transport layer, then run "windbgrm -c -p-1" on the debuggee.

On the debugger machine, make sure that CSRSS.EXE and any dynamic-link

libraries (DLLs) that you are debugging in association with it are in

the same directory, and run WinDbg. To set the transport DLL, choose

Debug from the Options menu, choose Transport DLLs, and set the

transport DLL to TLPIPE. Set the host name entries to be the machine

name of the debuggee.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


INF: Differences Between the Win32 SDK and 32-Bit VC++

Article ID: Q105679

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The following is a list of items included in the retail Win32 SDK that are

not included in the 32-bit Edition of Visual C++ (Intel only):

MORE INFORMATION

================

Tools

-----

   WinDbg/WinDbgRM

   Process Walker

   Working Set Tuner (WST)

   WinObj

   Setup Toolkit

   Microsoft Test

   Software Compatibility Test (SCT)

   API Profilers: CAP and WAP

   Symedit

   masm386

   Font Editor

Documentation

-------------

   LM API Reference (LMAPI.HLP)

   SNMP Programmer's Reference (SNMP.TXT)

   Generic Thunks (GENTHUNK.TXT)

   File Formats (CUSTCNTL.TXT, ENHMETA.TXT, PE.TXT, RESFMT.TXT)

Samples

-------

   BNDBUF                         MFEDIT

   BOB (named EXITWIN in VC++)    MIDIMON

   CDTEST                         MINREC

   CPL                            MSGTABLE

   DYNDLG                         NTFONTS

   GUIGREP                        NTSD

   LARGEINT                       PDC

   LOGGING                        RESDLL

   LOWPASS                        REVERSE

   MANDEL                         SCRNSAVE

   MAPI                           SEMAPHOR

   MAZELORD                       SPINCUBE

   MCITEST                        WINNET

Other

-----

   Device Driver Kit (DDK) headers and libraries

   Checked build of Windows NT

   RPC Toolkit

   POSIX headers and libraries

   Microsoft Foundation Classes (MFC) 1.0

The following is a list of items included in the 32-bit Edition of

Visual C++ that are not included in the retail Win32 SDK (Intel only):

Tools

-----

   Visual Workbench/AppStudio/Wizards

   bscmake

   Pharlap TNT DOS-Extender

   Spy++

   Source Profiler

   CodeView for Win32S

Samples

-------

   BOUNCE

   CVTMAKE

   EXITWIN (named BOB in the SDK)

Other

-----

   MFC 2.0

The preliminary Win32 SDK contained the compiler tools, while the

retail Win32 SDK does not. In addition, the preliminary Win32 DDK was

available separately, while the retail DDK is bundled with the retail

SDK.

The Win32 SDK has a separate "Win32s Programmer's Reference," while

VC++ has the same chapters as part of the "Programming Techniques"

manual.

There are tools whose names have changed and tools that are no longer

needed. The SDK linker is LINK32, the VC++ linker is LINK. The SDK

librarian is LIB32, the VC++ librarian is LIB. CVTRES existed in the

SDK to convert the .RES file produced by RC so that it could be used

by the linker, while VC++ has this functionality built into its

linker. These changes may affect your makefiles.

For more information on switching from the Win32 SDK to 32-bit VC++,

see the VC++ file MIGRATE.HLP.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


INF: Listing the Named Shared Objects

Article ID: Q105764

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Included with the Win32 SDK is an object viewer utility called WinObj that

be used to list named objects, devices, dynamic-link libraries (DLLs), and

so forth. To find objects such as pipes, memory, and semaphores, start

WinObj and select the folder BaseNamedObjects.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


PRB: RW1016 Error Due to Unexpected End of File (EOF)

Article ID: Q106064

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

The resource compiler generates the following errors when the .RC file

includes a .H file whose last line is a define (that is, there was no

final carriage return at the end of the #define statement):

   fatal error RC1004: unexpected EOF

   fatal error RW1016: RC terminating after preprocessor errors

CAUSE

=====

The resource compiler preprocessor follows C syntax. A newline character is

required on a #define statement.

RESOLUTION

==========

Add a carriage return following the #define.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsRc


INF: Additional Remote Debugging Requirement

Article ID: Q106066

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The printed and online documentation for remote debugging with WinDbgRm

fail to mention one requirement. The binaries must be in the same drive and

directory on both the target machine and the development machine.

WinDbg also expects to find the source files in the same directory in which

the the binary file was built, but will browse for the source if it is not

found in this location. WinDbg will automatically locate the source if the

files are specified to the compiler with fully qualified paths.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsWindbg


PRB: Problems with the Microsoft Setup Toolkit

Article ID: Q106382

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

1. When the /zi option is used with the Win32 DSKLAYT2.EXE to provide

   compression, it causes an access violation.

2. The Win32 Setup Toolkit does not contain a setup bootstrapper to

   copy the needed setup files to a temp drive and run the Setup

   program. Setup runs from floppy disks.

3. Install programs for applications that may run on Win32s must be

   created with the 16-bit version of the Setup Toolkit if the

   installation program will install Win32s. However, the 16-bit

   DSKLAY2.EXE cannot read the version information in a Win32 binary.

4. The Win32 DSKLAYT.EXE only shows 8.3 names in the list box.

5. The Setup program reports "out of memory" during installation, but there

   seems to be plenty of memory.

6. Installation fails from a CD-ROM. If the same files are copied from the

   CD to the hard disk, installation succeeds.

7. Setup programs created with the 32-bit setup toolkit will not run under

   Win32s.

RESOLUTIONS

===========

1. The fix for this problem is available in the Alpha SDK Update. This

   product contains Alpha development tools as well as updates to the

   x86 and MIPS components.

   Note that COMPRESS.EXE has been updated to use a better compression

   algorithm, and therefore /zi is no longer recommended for best

   compression. The option has been kept for compatibility reasons.

2. The bootstrapper is not necessary in a 32-bit environment. It is

   required for Windows because it is not possible to remove the

   floppy disk of a currently running Win16 application (the resources

   could not all be preloaded and locked). If you want to use a

   bootstrapper for compatibility, a 32-bit version is available on

   CompuServe.

3. If a Win32s installation is provided on a separate disk, the

   install program can be developed with the Win32 Setup Toolkit.

4. The program is actually a 16-bit program, and therefore it can

   display only the 8.3 name. Use 8.3 names for the source names and

   specify that the files be renamed (using the long names) when they

   are installed.

5. This error can be caused when a DLL on disk 1 is needed when

   when a different disk is currently inserted. To work around this

   problem, use LoadLibrary() to load the DLL.

6. This problem will be corrected in the Windows NT 3.5 SDK.

7. This problem will be corrected in the Windows NT 3.5 SDK.

Additional reference words: 3.10

KBCategory: Tls

KBSubcategory: TlsMss


FIX: Internal Error from NetUserEnum()

Article ID: Q108055

--------------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

--------------------------------------------------------------------------

SYMPTOMS

========

If you make a NetUserEnum() call from a down-level computer remoted to a

Windows NT machine, the error return is:

   2140 (NERR_InternalError).

This happens only if the down-level computer remotes the API to the Windows

NT computer and provides a buffer size that is greater than zero but less

than the size of one element of the data structure.

STATUS

======

Microsoft has confirmed this to be a problem in Windows NT and Windows NT

Advanced Server version 3.1. This problem was corrected in the latest U.S.

Service Pack for Windows NT and Windows NT Advanced Server version 3.1. For

information on obtaining the Service Pack, query on the following word in

the Microsoft Knowledge Base (without the spaces):

   S E R V P A C K

Additional reference words: 3.10

KBCategory: Prg

KBSubCategory: TlsLmapi


INF: Changes to the MSTest WFndWndC()

Article ID: Q108227

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

A change made to MS-TEST WFndWnd() and WFndWndC() may cause them not to

work as they did previously. Specifically, treatment of the first parameter

of WFndWnd() and WFndWndC() has changed.

Previously, "" and NULL resulted in the caption of the window being

ignored. Now, "" means the window must have an empty caption and NULL means

to ignore the caption altogether.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: TlsMisc


INF: Sharing All Data in a DLL

Article ID: Q109619

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Win32 dynamic-link libraries (DLLs) use instance data by default in Windows

NT. This means that each application that uses a DLL gets its own copy of

the DLLs data. However, it is possible to share the DLL data among all

applications that use the DLL.

If you only need to share some of the DLL data, we recommend creating a

new section and sharing it instead. For additional information, please see

the following article(s) in the Microsoft Knowledge Base:

   ARTICLE-ID: Q89817

   TITLE     : INF: How to Specify Shared and Nonshared Data in a DLL

If you want to share *all* of the DLL static data, it is important to

do two things:

 - First, the DLL must use the DLL version of the C Run-time (for example

   CRTDLL.DLL or MSVCRT10.DLL). Please see your product documentation for

   more information about using the C Run-time in a DLL.

 - Second, you will need to specify that both .data and .bss are shared.

   Often, this is done in the "SECTIONS" portion of the .DEF file. For

   example:

      SECTIONS

         .bss  READ WRITE SHARED

         .data READ WRITE SHARED

   If you are using Visual C++ for Windows NT, you will have to specify

   this using the -section switch on the linker. For example:

      link -section:.data,rws -section:.bss,rws

Only static data will be shared. Memory allocated dynamically with calls to

APIs/functions such as GlobalAlloc() or malloc() will still be specific to

the calling process.

The system will try to load the shared memory block at the same address in

each process. However, if the block cannot be loaded into the same memory

address, the system allocates a new block of memory for that process and

the memory is not shared. No run time warnings are given when this happens,

therefore, named shared memory is generally a safer option.

MORE INFORMATION

================

The C Run-time uses global variables. If the CRT is statically linked to

the DLL, these variables will be shared among all clients of the DLL and

will most likely cause an exception c0000005.

The reason you need to specify both .data and .bss as shared is because

they each hold different types of data. The .data section holds initialized

data and the .bss section holds the uninitialized data.

One reason for sharing all data in a DLL is to have consistent behavior in

the DLL between Win32 (running on Windows NT) and Win32s (running on

Windows 3.1). When running on Win32s, a 32-bit DLL shares its data among

all of the processes that use the DLL.

Note that it is not necessary to share all data to behave identically

between Win32 and Win32s. The DLL can use thread local storage (TLS) on

Win32s to store variables as instance data. For additional information,

please see the following article(s) in the Microsoft Knowledge Base:

   ARTICLE-ID: Q109620

   TITLE     : INF: Creating Instance Data in a Win32s DLL

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: BseDll


INF: Creating Instance Data in a Win32s DLL

Article ID: Q109620

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s versions 1.0 and 1.1

----------------------------------------------------------------------

SUMMARY

=======

The Win32 dynamic-link libraries (DLLs) that are running on Win32s use

shared data by default. This means that any global data in the DLL is

shared by all processes that use the DLL. Thread local storage (TLS) can be

used to create instance data; that is, data in the DLL that is specific to

each process.

The Win32s "Programmers Reference" mentions that TLS can be used to create

instance data, but provides no details. The sample code below shows the

source for a DLL that uses instance data on both Win32 and Win32s. The

sample code was built using Microsoft Visual C++, 32-bit edition.

If you use a development environment that does not have similar support for

TLS, you should still be able to use the API (application programming

interface) calls. The API calls for TLS are TlsAlloc, TlsGetValue,

TlsSetValue, and TlsFree.

MORE INFORMATION

================

One reason for wanting to create instance data on Win32s is to create a DLL

that behaves identically on Win32s and Win32. Another way to create a DLL

that behaves identically on Win32s and Win32 is to share all of the data in

the Win32 DLL. For additional information, please see the following

article(s) in the Microsoft Knowledge Base:

   ARTICLE-ID: Q109619

   TITLE     : INF: Sharing All Data in a DLL

Sample Code

-----------

/* Compile options used: /LD /MD

*/

int __declspec(thread) nVar = 0;

int __declspec(dllexport) GetVar()

{

    return nVar;

}

void __declspec(dllexport) SetVar(int nNew)

{

    nVar = nNew;

}

Additional reference words: 1.00 1.10

KBCategory: Prg

KBSubcategory: W32s


DOCERR: Errors in Win32s Compatibility

Article ID: Q113679

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

The following Win32 API (application programming interface) functions are

listed in the Win32 Programmer's Reference as being supported under Win32s.

This is incorrect. These Win32 APIs are not supported under Win32s:

   GetCharWidth32

   GetKBCodePage

   GetTextExtentPoint32

   ScrollWindowEx

   WNetAddConnection

   WNetAddConnection2

   WNetCancelConnection

   WNetCancelConnection2

   WNetCloseEnum

   WNetConnectionDialog

   WNetDisconnectDialog

   WNetEnumResource

   WNetGetConnection

   WNetGetLastError

   WNetGetUser

   WNetOpenEnum

The following Win32 APIs and messages are not listed in the Win32

Programmer's Reference as being supported under Win32s. This is incorrect

These Win32 APIs and messages are supported under Win32s:

   CopyMemory

   FillMemory

   FormatMessage

   GetThreadSelectorEntry

   LoadLibraryEx

   MoveMemory

   All OLE 1.0 APIs

   TlsAlloc

   ZeroMemory

   WM_COPYDATA

The following Win32 APIs and CRT (C Run-time) routines are supported under

Win32s, with the restrictions noted.

Function                         Associated Restriction

=======================================================================

CreateFileMapping                SEC_COMMIT is supported, but not

                                 SEC_IMAGE, SEC_NOCACHE or SEC_RESERVE

-----------------------------------------------------------------------

CreateDIBitmap                   DIB_PAL_INDICES is not supported

CreateDIBPatternBrush

CreateDIBPatternBrushPt

GetDIBits

SetDIBits

SetDIBitsToDevice

StretchDIBits

-----------------------------------------------------------------------

GetSystemPaletteEntries          The fourth parameter cannot be NULL

-----------------------------------------------------------------------

spawn                            P_WAIT is not supported

=======================================================================

Additional reference words: 1.10

KBCategory: Ref

KBSubCategory: W32s


BUG: Win32s 1.1 Bug List

Article ID: Q113739

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

SUMMARY

=======

The following is a list of known problem in Win32s version 1.1. Microsoft

has confirmed these to be problems in Win32s version 1.1. Problems marked

with a hyphen ("-") will be corrected in Win32s version 1.15. Problems

marked with an asterisk ("*") will be corrected in Win32s version 1.2.

 - Setup fails if there are 40 groups in Program Manager.

 - WinFile generates a general protection (GP) fault while viewing file

   properties.

 - The Universal Thunk (UT) callback returns a WORD, rather than a DWORD.

 - The LA (linear address) Table is limited to 256 entries. This limits the

   number of VirtualAlloc() calls that will succeed.

 - Win32s does not handle paths that contain an ampersand ("&") or a number

   sign ("#").

 - FP (floating point) exceptions are not trapped by SEH (structured

   exception handling. FP exceptions in 32-bit code which are called from

   16-bit code via UT can cause a GP fault in WIN87EM.

 - Thread Local Storage (TLS) data is allocated from a limited heap size.

   This can cause applications that use a lot of TLS data to fail to load.

 - CB_FINDSTRING and LB_FINDSTRINGEXACT are not thunked correctly from  a

   16-bit application to a 32-bit application.

 - Dialog templates passed from a 32-bit applications are corrupted.

 - If a DDE client responds to INITIATE for which it is also the server,

   lParam is packed incorrectly.

 * fstat() always returns that rt_mode is read/write.

 * chdrive() does not retain the current working directory. chdrive()

   always uses the root directory.

 - ChooseFont()'s referenced CHOOSEFONT structure has blue value set to 0

   with CF_EFFECTS.

 - CopyFile() uses the current time rather than the file time.

 - CreateFile() does not parse UNC names correctly.

 - CreateProcess() does not set current directory correctly.

 - CreateProcess() ignores window size and window position.

 - CreateProcess() debug version corrupts the environment if

   lpApplicationName != NULL.

 - CreateProcess() returns failure if the child does not call GetMessage()

   or yield in some way before control goes to the parent.

 - CreateProcess()'s dwFlags is ignored when starting Win16 applications,

   while wShowWindow is always passed.

 - CreateWindowEx()'s CW_USEDEFAULT flag is not handled, which causes

   problems with using WM_VISIBLE.

 - EnumMetaFile()'s handles array is corrupted.

 - EnumPropsEx() enumerates non-existing properties.

 - EqualRect() returns TRUE for rectangles that are lines.

 - FindFirstFile() error code is set to ERROR_NO_MORE_FILES instead of

   ERROR_FILE_NOT_FOUND if there are no matches for the search pattern.

 - FindFirstFile() may use a bad DTA, causing stack corruption.

 - GetClassInfo() WNDCLASS buffer is corrupted if passed an invalid class.

 * GetFileInformationByHandle() support added in version 1.15, but file

   attribute returned is always 0.

 - GetFilePointer() returns valid value when given invalid handle.

 - GetFileSize() moves the file pointer.

 - GetFileVersionSize() causes a GP fault when 16-bit applications for

   Windows call the function from a 32-bit DLL.

 - GetKerningPairs() results are not in Win32 format.

 - GetModuleFileName() causes the OFSTRUCT structure to be truncated in 16-

   bit applications calling this function on a 32-bit DLL.

 - GetModuleFileName()'s char count returned includes the terminating NULL

   character.

 - GetOpenFileName() call fails with OFN_ENABLETEMPLATEHANDLE.

 - GetOpenFileName() has a hook you can use to trap  WM_INITDIALOG to get

   the address of OPENFILENAME struct, but the pointer is  corrupted by the

   next message.

 - GetOutlineTextMetrics() returns OUTLINETEXTMETRIC structure with Windows

   3.1 format rather than Win32 format.

 - GetOutlineTextMetrics()'s OUTLINETEXTMETRIC UnderscorePosition,

   UnderscoreSize, and otmItalicAngle are incorrect.

 - GetSystemInfo() returns an incorrect lpMinimumApplicationAddress and an

   incorrect lpMaximumApplicationAddress.

 - GlobalCompact() exception occurs when the value is larger than available

   memory.

 - HeapAlloc/malloc() are slow because debug check was left in the code.

 - IsCharAlpha() returns 0 for characters 128-255.

 - LoadLibrary() fails to report unsucessful load of 16-bit DLLs (should

   return ERROR_BAD_EXE_FORMAT).

 - LoadLibrary() fails after 4591 calls due to a memory leak.

 - LoadLibrary() was fixed to work from a 32-bit DLL called by a 16-bit

   application.

 - LoadModule() does not pass cmdshow so applications get SW_SHOWNORMAL.

 - LocalAlloc() fixed to work from a 32-bit DLL called by a 16-bit

   application.

 - MultiByteToWideChar() has the wrong string returned with USE_GLYPHCHARS.

 - NetAccessAdd(), NetApiBufferAllocate(), NetUseGetInfo(), and

   NetUserSetGroups() all are not exported by NETAPI32.DLL.

   NOTE: These functions are not supported.

 - OpenFile() does not parse UNC names correctly.

 - PeekMessage() causes RIP in debug windows if hwnd is NULL.

 - PlayMetaFileRecord()'s handles array is corrupted.

 - PolyPolygon() fails with more than 16 polygons.

 - PrintDlg() incorrectly frees global memory and fails with MFC sample.

 - SetClipboardData()'s 32-bit memory is not freed when clipboard is

   emptied.

 - SetErrorMode()'s SEM_NOOPENFILEERRORBOX does not work. The message box

   still appears.

 - SetFilePointer() returns a valid value if given an invalid handle.

 - SetProp()'s seventeeth call fails if lpsz is a string rather than an

   atom.

 - SetWindowLong()'s GWL_USERDATA always returns 1.

 - TrackMenuPopup()'s optional lprc parameter is not handled correctly.

 - waveOutGetDevCaps()'s WAVEOUTCAP buffer not filled correctly for the

   SoundBlaster.

 - waveOutWrite()'s WOM_DONE messages are not posted with multiple buffers

   and loop play.

 * WinExec() will cause 16-bit applications which are launched to GP fault.

Additional reference words: 1.10

KBCategory: Prg

KBSubCategory: W32s


INF: Win32s 1.1 Limitations

Article ID: Q114340

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s, version 1.1

----------------------------------------------------------------------

SUMMARY

=======

The following is a list of limitations of Win32s, not including the

complete list of unsupported Win32 APIs.

MORE INFORMATION

================

 - Thread creation is not supported.

 - Win32s uses the Windows 3.1 nonpreemptive scheduling mechanism.

 - Win32s has a shared address space, so instance data for dynamic link

   libraries (DLLs) is not supported.

 - Win32 processes should be started from a Win16 application through

   WinExec() or Int 21 4B. LoadModule() does not start a Win32 process.

 - Win32 applications cannot use the EM_SETHANDLE or EM_GETHANDLE messages

   to access the text in a multiline edit control. These messages allow the

   sharing of local memory handles between an application and USER.EXE. In

   Win32s, an application's local heap is 32-bit, so USER.EXE cannot

   interpret the local handle. To read and write multiline edit control

   text, an application should use WM_GETTEXT and WM_SETTEXT.

   Text for multiline edit controls is stored in the 16-bit local heap in

   DGROUP, which is allocated by Windows 3.1 for the WIN32S.EXE stub that

   is loaded before each Win32 application is loaded. This means that the

   size of edit control text is limited to somewhat less than 64K.

 - The CBT hook thunks do not copy back the contents of structures, so any

   changes will be lost.

 - Win32 applications should not call through return from SetWindowsHook().

   SetWindowsHook() returns a pointer to the next hook in the chain. To

   call this function, the application is supposed to call DefHookProc()

   and pass a pointer to a variable where this address is stored. Because

   Win32s simulates the old hook API in terms of the new, SetWindowsHook()

   actually passes back a hook handle, not a function pointer.

 - Win32s requires all modules to be linked with 4K alignment. Temporarily,

   the loader supports 64K as well.

 - Integer ID must be a 16-bit value.

 - PostMessage() and PeekMessage() do not thunk structures. These functions

   do not allocate space for repacking structures, because there is no way

   to know when to free up the space.

 - Private application messages should not use high word of wParam. Win32s

   uses Windows 3.1 to deliver window messages. For unknown messages,

   wParam is truncated to make it fit into 16 bits. Therefore, Win32

   applications should not put 32-bit quantities into the wParam of

   privately defined messages, which are unknown to the thunk layer.

 - Win32s allows a Win32 application to allocate memory at a specific

   address; however, because of the shared address space on Windows 3.1,

   this is more likely to fail under Win32s.

 - DDE messages are always posted, not sent, except for two:

   WM_DDE_INITIATE and WM_DDE_ACK, responding to the former. The sent form

   of WM_DDE_ACK is different from the posted form. When sent, no thunking

   of lParam is necessary when going between 16- and 32-bit format.

   However, when posting, the lParam parameter is repacked as two DWORDs

   into private memory, allocated by COMBO.DLL (or by USER.DLL in Windows

   NT). The thunk layer makes this distinction through the InSendMessage()

   function. Therefore, a Win32 application should not do anything in the

   processing of a WM_DDE_INITIATE message that would cause the return code

   from InSendMessage() to be FALSE.

 - The following DDE messages are handled differently by different

   applications under Windows and Win32:

      WM_DDE_ACK

      WM_DDE_ADVISE

      WM_DDE_DATA

      WM_DDE_EXECUTE

      WM_DDE_POKE

   Because of widening of handles, there is not enough space in the Win32

   message parameters for all the Windows 3.1 data. Win32 applications are

   required to call helper functions that package the data into memory

   (DDEPACK structure) referenced by a special handle. Win32s implements

   the helper functions, and allocates the DDEPACK structure on behalf of

   16-bit code when necessary.

   As with other memory handles shared through DDE, there are rules

   concerning who frees the memory allocated by these helper routines:

      lParam = PackDDElParam(...)

      if( PostMessage(...,lParam) )

         receiving window has obligation of freeing memory

         lParam now invalid for this process

      else

         FreeDDElParam(...,lParam)

   A Win32s hook procedure that has called CallNextHookProc() should not

   use the lParam handle if the latter's return code indicates that the

   message has been processed. The hooks that could possibly process a DDE

   message are:

      WH_DEBUG

      WH_HARDWARE

      WH_KEYBOARD

      WH_MOUSE

      WH_MSGFILTER

      WH_SYSMSGFILTER

   In each case, if the hook proc (and therefore CallNextHookEx()) returns

   a non-zero value, the message was either discarded or processed.

   WndProcs should not use the lParam of a DDE message after handing it off

   to any other message API, because they cannot know if the message has

   been processed and therefore must assume that it has been.

 - WDEB386 does not support FreeSegment() for 32-bit segments. Win32s

   Kernel Debugger support depends on it.

 - Resource table size for PE is limited to 32K (not including the resource

   data).

 - SetClipbrdData() must be used only with global handle. Otherwise the

   data can not be accessed by other applications.

 - Win32s supports printing exactly as Windows 3.1 does. Win32s does not

   add beziers, paths, or transforms to GDI; to let applications use these

   features on PostScript printers, you must call the Escape() function

   with the appropriate escape codes.

   Applications link to Windows 3.1 printer drivers through the

   LoadLibrary() and GetProcAddress() APIs, which have special support for

   this purpose. There is no mechanism allowing a Win32 application to link

   to a 16-bit DLL.

 - Win32s does not support the following GDI escape codes:

      BANDINFO                 ;24

      GETSETPAPERBINS          ;29

      ENUMPAPERMETRICS         ;34

      EXTTEXTOUT               ;512

      SETALLJUSTVALUES         ;771

 - Integer atoms must be in the range 0 - 0x3FFF. This restriction is

   necessary for the current implementation of the window properties API

   thunks: SetProp(), GetProp(), RemoveProp(), EnumProps(), and

   EnumPropsEx(). Integer atoms above 0x4000 are rejected by the thunk

   layer.

 - Arrays must fit in 64K after converting to 16-bit format. An array

   passed to a function such as SetCharABCWidths() or Polyline() must fit

   within 64K after its elements have been converted to their 16-bit form.

   Its 32-bit form may be bigger than 64K.

 - Temporarily, all Windows 3.1 APIs that return void return 1 to the Win32

   application.

 - Win32 child window ID's must be sign-extended 16-bit values. This

   excludes the use of 32-bit pointer values as child ID's.

 - When calling PeekMessage(), a Win32 application should not filter any

   messages for Windows 3.1 internal window classes (button, edit,

   scrollbar, and so forth). The messages for these controls are mapped to

   different values in Win32, and checking for the necessity of mapping is

   time-consuming.

 - The dwThreadId parameter in SetWindowsHookEx() is ignored. The

   dwThreadId is translated to hTask in Windows 3.1. There's a bug in

   Windows 3.1 where if hTask!=NULL, the call may fail. This needs further

   investigation.

 - Floating point (FP) emulation by exception cannot be performed in 16-bit

   applications. When tasks are switched between applications, the CR0-EM

   bit state is not preserved, in order to support 32-bit application FP

   emulation by exception without breaking the existing 16-bit applications

   that use FP instructions. The CR0-EM bit is assumed to be cleared during

   execution of 16-bit-application FP instructions. Upon executing a 16-bit-

   application FP instruction, the bit is cleared and reset when switching

   back to a 32-bit application. The CR0-EM bit management is done in the

   Win32s VxD, thus disabling the possibility of getting an int 7 exception

   just by setting the CR0-EM bit in a 16-bit application.

 - EndDialog() nResult parameter is sign-extended. Applications specify the

   return value for the DialogBox() function by way of the nResult

   parameter to the EndDialog() function. This parameter is of type "int",

   which is 32-bit in Win32s. However, this value is thunked through to the

   Windows 3.1 EndDialog() function, which truncates it to a 16-bit value.

   Win32s sign-extends the return code from DialogBox().

 - GetClipBox() returns SIMPLEREGION(2) and COMPLEXREGION(3). Because

   Windows NT is a preemptive multitasking system, GetClipBox() on Windows

   NT never returns SIMPLEREGION(2); the reason for this is that between

   the time the API was called and the time the application gets the

   result, the region may change. Win32s can return both SIMPLEREGION(2)

   and COMPLEXREGION(3).

 - PeekMessage() filtering for posted messages (hWnd==-1) is not supported.

   The hWnd is replaced with NULL.

 - Message queue length is limited to Windows default: 8 (or whatever the

   length) was set by DefaultQueueSize=n in WIN.INI. This limit may be

   increased in the future to a larger size, but there will always be a

   limit.

 - GetFileTime() and SetFileTime() process only the lpLastWriteTime

   parameter and return an error if this parameter is not supplied.

 - The precision of the time of a file is 2 seconds (DOS limitation).

 - CommDlg does not support private dialog templates. The dialog templates

   need to be converted back and forth between 16- and 32-bit formats.

   Until Win32s 1.15, private dialog templates are not supported.

 - GetPrivateProfileString() returns an error when the lpszSection

   parameter is NULL instead of giving all the section names in the

   inifile, as it does under Windows NT.

 - TLS locations are the same in all processes for a specific DLL. This is

   because Win32s does not support instance data for DLLs. The TLS

   locations are unique per DLL. Each DLL should call TlsAlloc() only once

   per index if it is running under Win32s. The index returned is then

   valid for all Win32 processes. The DLL can maintain several indices.

 - GlobalCompact() is thunked through to the Windows 3.1 GlobalCompact().

   This API has no effect on memory allocated through VirtualAlloc(), which

   does not come from the Win3.1 global heap.

 - GetVolumeInformation() does not support the Volume ID.

 - GetFileInformationByHandle() and the CRT fstat() that uses it are not

   supported. Both are supported in Win32s, version 1.15. The

   dwFileAttribute of GetFileInformationByHandle() is always zero. This

   also causes fstat() to return an st_mode of read/write regardless the

   actual attribute.

 - CreatePolyPolygonRgn() requires a closed polygon, as it does under

   Windows 3.1. If the polygons are not closed, the Windows NT call closes

   the polygons for you. In Windows 3.1/Win32s, if the polygons are not

   closed, the call does not create the region correctly or returns an

   error for an invalid parameter.

 - Win32s does not support DIB_PAL_INDICES option for SetDIBits(). It will

   be supported in future release. DIB_PAL_PHYSINDICES and

   DIB_PAL_LOGINDICES are not supported either.

 - The WH_FOREGROUNDIDLE hook type is not supported. Windows 3.1 does not

   provide the necessary support.

 - The brush styles BS_DIBPATTERNPT and BS_PATTERN8X8 are not supported and

   cause an error to be returned.

 - The hFile in DLL and PROCESS events is not supported under Win32s

   because there is no support for duplicating file handles between

   processes (basically an MS-DOS limitation).

   There are two ways to access the image bytes: ReadProcessMemory() or

   open the file in compatibility mode (the name is provided in

   lplpImageName).

 - Under Windows NT, NetBIOS keeps a different name table for each process.

   On Win32s, there is only one NetBIOS name table for the system. Each

   name (group or unique) added by a process is kept in a doubly linked

   list. Through NCBRESET or by destroying the process, we delete all the

   names that were added by the process. Win32s does not implement the full

   NetBIOS 3.0 specification, which has a separate name table per process.

 - When calling 32-bit code from 16-bit code with UT (for example, from

   interrupt routine) the stack must be at least 10K. The interrupt routine

   must ensure that the stack will be big enough.

 - Get/SetThreadContext() can be called only from within an exception. At

   all other times, this function returns FALSE and the error code is set

   to ERROR_CAN_NOT_COMPLETE.

 - CreateProcess() PROCESS_INFORMATION is not supported for 16-bit

   applications. A valid structure must be passed to CreateProcess(), but

   the function fills all the fields with NULLs and zeroes.

 - Win32s does not support NT event mechanism; therefore, the ncb_event

   field in NCB structure is not supported.

 - CreateFileMapping() does not support SEC_NOCACHE nor SEC_NOCOMMIT. The

   call fails with ERROR_INVALID_PARAMETER.

 - Always use device-independent bitmaps for color bitmaps. Win32s supports

   the four Win32 "device-dependent" bitmap APIs. These are device-

   dependent in the sense that the bitmap bits are supplied without a color

   table to explain their meaning.

      CreateBitmap

      CreateBitmapIndirect

      GetBitmapBits

      SetBitmapBits

   These are well-defined and fully supported for monochrome bitmaps. For

   color bitmaps, these APIs are not well defined and Win32s relies on

   Windows 3.1 for their support. This means that an application cannot

   know the format of the bits returned by GetBitmapBits() and should not

   attempt to directly manipulate them. The values returned by

   GetDeviceCaps() for PLANES and BITSPIXEL, and the values returned by

   GetObject() for a bitmap, do not necessarily indicate the format of the

   bits returned by GetBitmapBits().It is possible for the GDI DIB APIs to

   be unsupported on some displays. However, it is now rare for display

   drivers to not support DIBs. The one case where it is not uncommon to

   encounter a lack of DIB support is with printer drivers, which may not

   support the GetDIBits() API, though most do support the SetDIBits() API.

   Win32s does not transform the bits in any way when passing them on to a

   Windows 3.1 API. When running an application that creates a device-

   dependent bitmap through CreateBitmap() or CreateBitmapIndirect(), be

   aware that the bits it is passing in may not be in the right format for

   the device. Windows NT takes care of this by treating the bits as a DIB

   whose format is consistent with the PLANES and BITSPIXEL values; but

   Win32s simply passes them through.

 - After calling FindText(), an application cannot directly access the

   FINDREPLACE structure. When an application calls the common dialog box

   function FindText(), it passes a FINDREPLACE structure. The FindText()

   dialog box communicates with the owner window through a registered

   message, in which the lParam points to the structure. The thunks repack

   this structure in place, so that unless the application is processing

   the registered message, it should not access the structure.

 - Subclassing a window that owns a FindText() common dialog does not work.

   The FindText() thunk repacks the FINDREPLACE structure in place. This

   means that 32-bit WndProcs cannot subclass 16-bit owners of FindText()

   dialog boxes without likely trashing four bytes beyond the end of the

   structure, because the 32-bit FINDREPLACE is four bytes bigger than the

   16-bit version.

   For 32-bit owners of the dialog box, there are also problems. Whenever

   the structure might be referenced by 16-bit code, it needs to be in the

   16-bit format. However, when the FindText() dialog box terminates, the

   structure needs to be in 32-bit format so that the application can read

   the final values. The dialog box indicates to its owner that it is about

   to be destroyed by sending the commdlg_FindReplace message with the

   FR_DIALOGTERM bit set in the Flags field of the FINDREPLACE structure.

   After sending this message, the FindText() dialog does not reference the

   structure anymore, so that the commdlg_FindReplace thunk leaves it in 32-

   bit format.

   The problem occurs when the owner has been subclassed. Once the message

   has moved to the 32-bit side, the structure is not reconverted to 16-

   bit. Suppose the dialog box owner was subclassed by a 16-bit WndProc,

   which was in turn subclassed by a 32-bit WndProc. When a message is sent

   to the owner, it will first go to 32-bit, then to 16-bit, then back to

   32-bit to the original WndProc:

   1. 16->32 message sent to 32-bit subclasser (repacked to 32-bit)

   2. 32->16 message sent to 16-bit subclasser (not repacked)

   3. 16->32 message sent to 32-bit original WndProc (not repacked)

   The 16-bit subclasser cannot interpret the message parameters because

   they are in 32-bit format. Between steps 2 and 3, the structure is not

   repacked because it's already in 32-bit format.

   When a Win32 application calls FindText(), allocate the following:

   1. A structure that contains the htask of WIN32S.EXE

   2. The original 32-bit FINDREPLACE pointer

   3. A count of the number of times the structure has been thunked without

      returning

   4. A 16-bit format copy of FINDREPLACE

   The structure is repacked into the 16-bit version and this copy is

   passed to Windows. The count is initially zero. When the

   commdlg_FindReplace message is sent in either direction (16->32 or

   32->16), repack the structure on the stack. If it was originally 32-bit,

   increment the count. When returning, unpack the structure and, if

   originally 32-bit, decrement the count. If the Flags field of the

   structure has the FR_DIALOGTERM bit set, the structure is originally 32-

   bit, and the count goes to 0 on a return, then repack the structure back

   to the original 32-bit space.

Additional reference words: 3.10 1.10

KBCategory: Prg

KBSubcategory: Win32s


PRB: "Out of Memory Error" in the Win32 SDK Setup Sample

Article ID: Q114610

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

When a dialog box is shown using UIStartDlg() or a billboard is switched

during the file copy operation, you may receive an "out of memory" error.

The error will also occur in any setup program based on a modified version

of the SDK sample.

CAUSE

=====

The dialog box and billboard templates are stored as resources in

MSCUISTF.DLL. This DLL (Dynamic Link Library) is not loaded at the

beginning of the setup program but is rather loaded and unloaded [using

LoadLibrary() and FreeLibrary()] around each call to UIStratDlg() and when

billboards are switched. Hence, each time a dialog or billboard is

displayed, floppy disk #1 has the potential of being accessed. If disks

have been swapped due to the installation process such that disk #1 is no

longer in the drive, you will receive an out of memory error when

LoadLibrary() is called on MSCUISTF.DLL.

RESOLUTION

==========

To solve the problem, call LoadLibrary() at the beginning of WinMain() and

call FreeLibrary() and the end of WinMain(). This way the DLL is always in

use and will never be unloaded until the setup is done.

Additional reference words: 3.10

KBCategory:

KBSubcategory: TlsMss


PRB: Page Fault in WIN32S16.DLL Under Win32s

Article ID: Q115082

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s, versions 1.1 and 1.15

----------------------------------------------------------------------

SYMPTOMS

========

Start two instances of the Win32 application under Win32s. Close one

instance, then close the other instance. A page fault is generated in

WIN32S16.DLL. Under Win32s, version 1.1, a dialog box appears. Under

Win32s, version 1.15, the error only appears in the output from the debug

version of Win32s.

CAUSE

=====

This problem can be caused by using the static C run-time (CRT) libraries

or using MSVCRT10.DLL. Note that even if the application does not make any

CRT calls, one of its DLLs may call the CRT initialization and cleanup

code. The CRT code makes the following sequence of API calls:

   DeleteCriticalSection

   DeleteCriticalSection

   DeleteCriticalSection

   TlsFree

   VirtualFree

   VirtualFree

   VirtualFree

When the second application instance terminates, it faults before it makes

the call to TlsFree(). The CRT has two blocks, one that contains strings

from the environment and one that contains pointers to the first blocks.

These are allocated by the first process that attach to the DLL. Other

processes that attach do not allocate these blocks. When processes are

terminated, these two blocks are freed. However, this succeeds only when

the process that owns the memory frees them. Any other process that tries

to access these blocks will fail.

RESOLUTION

==========

Because there is no instance data by default under Win32s, DLLs should use

the CRT in a DLL instead of linking to the CRT statically. MSVCRT10.DLL

(which comes with Visual C++) is not compatible with Win32s because

MSVCRT10.DLL falsely assumes that Win32s implements instance data, which is

only available on Windows NT. Therefore, until an updated MSVCRT.LIB file

is released, use CRTDLL.LIB (which comes with the Win32 SDK) because Win32s

has its own CRTDLL.DLL file that was specifically designed for this use.

MORE INFORMATION

================

The real problem is that memory is allocated for several applications. The

allocation is done by the first application. When this application

terminates, it takes with it all of its memory. This means that each time

the remaining applications try to access this memory, an error occurs.

Symptoms include data corruption, hanging, or the WIN32S16.DLL page fault

mentioned above.

Additional reference words: 1.10 1.15

KBCategory: Prg

KBSubcategory: W32s


INF: Win32 SDK 3.5 LINK32.EXE Calls CVTRES.EXE

Article ID: Q115234

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.5

----------------------------------------------------------------------

SUMMARY

=======

When you are building an application with the Win32 SDK, you can use the

CVTRES utility to add a COFF wrapper to files produced by the resource

compiler (RC) so that the files can be accepted by the linker. In the Win32

SDK, version 3.1, the sample makefiles were set up so that RC produced a

.RES file, which CVTRES converted into an .RBJ file. The .RBJ file was then

linked into the executable file.

With the tools that are included in the Win32 SDK, version 3.5, it is no

longer necessary to call the CVTRES utility directly to convert .RES files

to .RBJ files. The linker (LINK) calls CVTRES directly when it detects an

unconverted .RES file.

The linker included in VC++ 1.0 for Windows NT converts the .RES files

internally, without calling the CVTRES utility, so that CVTRES is not

shipped with this product. Therefore, if you copy the Win32 SDK 3.5 linker

to your \MSVCNT\BIN directory in order to use it with the VC++ 1.0 for

Windows NT tools, make sure that the linker can locate the CVTRES utility

as well. That is, it needs to be copied to the \MSVCNT\BIN directory or it

needs to be made available through the PATH environment variable. If the

linker cannot find the CVTRES.EXE file, the following error is generated:

   LNK1123: failure during conversion to COFF : file invalid or corrupt

MORE INFORMATION

================

All of the Win32 SDK sample makefiles were updated for version 3.5, so that

they no longer include lines that begin $(cvtres) or CVTRES.EXE. The

dependencies between .RES files and .RBJ files were also removed from the

makefiles. The .RES files are now linked to the executable files directly.

Additional reference words: 3.5

KBCategory: Tls

KBSubcategory: TlsMisc


INF: Win32 Subsystem Object Cleanup

Article ID: Q89290

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The Win32 subsystem guarantees that all Win32 objects owned by a

process will be freed when an application terminates. To accomplish

this, the Win32 subsystem keeps track of who owns these objects; it

also keeps a reference count. Reference counts are used when the

object is owned by more then one process. For example, a memory mapped

file can be used to provide interprocess communication, where more

than one process would own that object. The subsystem must make sure

that the reference count is zero before the object can be freed.

Freeing of Win32 objects can occur at different times. In general, it

occurs at process termination, but for some objects, it occurs at thread

termination.

NOTE: When running Win32 applications with Windows 3.1 using the Win32s

environment, it is the responsibility of the Win32 application to ensure

that all allocated GDI objects are deleted before the program terminates.

This is different from the behavior of the application with Windows NT.

With Windows NT, the GDI subsystem cleans up all orhphaned GDI objects.

Because there is no GDI subsystem with Windows 3.1, this behavior is not

supported.

MORE INFORMATION

================

At process or thread termination, the Win32 subsystem searches its lists to

find objects owned by this process or thread. Those that are owned by the

terminating process or thread and whose reference counts will be set to

zero when the process or thread is fully terminated will be freed.

The freeing of objects is slightly different for Win32 applications running

under Win32s on Windows 3.1. The 16-bit objects (GDI objects, windows,

global memory, etc.) follow the same clean-up rules as Win16 applications

do under Window 3.1. The 32-bit objects, such as memory allocated via

VirtualAlloc(), shared memory via mapped file I/O, 32-bit modules, thunks

allocated on the fly (for hook procedures, wndprocs etc.) are all handled

by Win32s and freed at process termination.

The following is a list of Win32 objects. Note that it may not be complete.

   BASE: console, event, file (including file mapping), mutex,

         semaphore, thread, process, pipe (including named pipes)

   GDI:  device context (DC), bitmap, pen, brush, font, region, palette

   USER: window, cursor, icon, menu, accelerator table, desktop,

         DDE communication objects, DDE conversation objects, dialog

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: SubSys


INF: No Subsystem Developer Kit or Support for Such a Kit

Article ID: Q89987

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

There is not a kit available for developers to write subsystems, nor are

there plans to provide such a kit. Furthermore, there is no documentation

or support available to develop a subsystem for Windows NT.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: SubSys


INF: Running Bound Applications Under Windows NT

Article ID: Q90913

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Bound applications are designed and built so they can be run under either

OS/2 or MS-DOS. The OS/2 subsystem is not available on MIPS; therefore,

bound applications will not run as OS/2 applications on MIPS.

When a bound application is run under Windows NT on an 80x86 system, the

application will automatically run under the OS/2 subsystem if it is

available.

MORE INFORMATION

================

The OS/2 subsystem is available by default on an 80x86 system. To

force bound applications to run as an MS-DOS application, you can

disable the OS/2 subsystem, but this is not recommended. Instead use

the FORCEDOS facility. Type "FORCEDOS /?" at the command line to get

help on FORCEDOS. It is not advised that you disable the OS/2

subsystem unless there is a very specific need that FORCEDOS does not

address.

To disable the OS/2 subsystem using RegEdit:

   Go to HKEY_LOCAL_MACHINE

   Go to SYSTEM

   Go to Current Control Set

   Go to Control

   Go to Session Manager

   Go to SubSystems

   Modify 'Optional: REG_MULTI_SZ OS/2 Posix'. Specifically, remove OS/2

   and reboot.

Once this is done, bound applications will run as MS-DOS applications.

Running an OS/2 application results in the following message:

   Cannot connect to OS/2 subsystem

WARNING: REGEDT32 is a very powerful utility that facilitates directly

changing the Registry database. Using REGEDT32 incorrectly can cause

serious problems, including hard disk corruption. It may be necessary to

reinstall the software to correct some problems. Microsoft does not support

changes made with REGEDT32. Use this tool AT YOUR OWN RISK.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: SubSys


PRB: GP Fault in OS/2 Subsystem

Article ID: Q92508

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

A general protection fault (GP fault) can occur in the OS/2 subsystem if

you have a corrupted registry entry for the subsystem. The system says:

   General Protection error occurred

   An OS/2 program caused a protection violation.

   The program will be terminated.

RESOLUTION

==========

A workaround is to use REGEDT32 to get to

   HKEY_LOCAL_MACHINE\

      SOFTWARE\

      Microsoft.

Select OS/2 Subsystem for NT and press the DEL key. Now restart your

machine. Logging off is not sufficient; you must reboot. The next time you

try to start an OS/2 application, the OS/2 server will rebuild the registry

item that you deleted.

Additional reference words: 3.10 GP-fault

KBCategory: Prg

KBSubcategory: SubSys


INF:  Binary and Source Compatibility Under Windows NT

Article ID: Q93213

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

There are currently three hardware platforms for which Win32 applications

can be written; they are Intel (x86), MIPS, and DEC Alpha. Binary

compatibility across these hardware platforms is not a viable alternative.

Therefore, Windows NT offers source compatibility. This means that

developers may create versions of their Win32 applications for each CPU by

recompiling.

For example, suppose that you have written a Win32 application in C and

have used a 32-bit compiler that targets the Intel platform. In order to

produce a Win32 application that runs on DEC Alpha, you would purchase a 32-

bit compiler that targets Alpha and recompile your code.

MORE INFORMATION

================

It is important not to confuse source compatibility across hardware

platforms with binary compatibility across application execution

environments. Windows NT and Win32s do support binary compatibility between

different application execution environments. For example, the typical

Win16 application can be run without modification on any Windows NT

machine. On the MIPS and Alpha platforms, this is achieved through

emulation. In addition, it is possible to design an x86 Win32 application

so that it runs on Windows 3.1. This is achieved through Win32s.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: SubSys


INF: Named Pipes Under WOW

Article ID: Q94948

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

A 16-bit application under Windows on Win32 (WOW) may use a named pipe

that was created previously by a 32-bit application; however, REDIR.EXE

must be included in the AUTOEXEC.BAT file for this to work properly.

Note that for local named pipes, networking doesn't need to be enabled.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: SubSys


INF: Some Subsystems Persevere Through Logons

Article ID: Q94995

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

Subsystems such as the Local Security Authority (LSA), the spooler, the

Win32 server, and the OS/2 subsystem do not terminate when the user logs

off, and then restart at next logon.

Windows on Win32 (WOW) is not a true subsystem; rather, it is a user-mode

program. When you run an MS-DOS program, the console you run it from has a

virtual DOS machine (VDM) attached to it until the console exits (which it

is forced to do at logoff). When you run the first Win16 program, the WOW

VDM is started and continues to run until the user logs off.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: Subsys


INF: Binary Compatibility Basics

Article ID: Q95162

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Because of differing instruction sets between processors, object code is

not binary-compatible across platforms. To enable object code compiled for

processor X to run on processor Y, a virtual machine must be created on

processor Y to emulate processor X's instructions, which results in a

considerable performance hit. For this reason, Windows NT offers a strong

source compatibility, which makes it a relatively simple matter to compile

the same code into native object code for each platform.

The Hardware Abstraction Layer (HAL), smooths over differences between

hardware implementations. All access to the hardware from the operating

system (OS) goes through the HAL, which makes changing of both the hardware

and the OS itself much simpler. The HAL, however, does not emulate the

instruction set of the platform; a common misconception.

MORE INFORMATION

================

Source code is compiled into executable or object code for the instruction

set of a specific processor or family (x86, 680x0, R3000/4000, and so

forth). This code runs natively only on that type of processor. Remember,

this reduces to 1's and 0's, hence binary, so even if two processors have a

large overlap in the available instructions (and they do; MOVs, XORs, or

whatever at the assembly language level), what is actually executed is not

even relatively "high level" human-readable assembly code but merely a

series of bytes that by convention/definition only are assigned the

meanings that are human-readable at the assembly language level.

For example, probably every microprocessor has an OR instruction. On the

Intel x86, the OR instruction may be represented in the instruction stream

by the bytes "09 [effective address]" (see page 456 of Microsoft's

80386/80486 Programming Guide, 2nd Ed.). On the R4000, however, it's nearly

guaranteed to be something different.

Thus, if you want to run an executable compiled for Intel on a MIPS chip,

you must run a program that behaves as an Intel instruction interpreter

(similar to a Basic interpreter, but much more complex). Such a program is

called an emulator, and will scan through the Intel object code and then in

turn execute equivalent commands in MIPS form on the processor. But the

emulator must do much more than that; it must also create a "virtual

machine," a complete software execution environment that behaves similar to

the original hardware/software environment that the executable was

originally compiled for.

Note that even in an ideal case, every processor X instruction requires

about 5-20 instructions on processor Y. The object code interpreter must

examine the next instruction/byte, compare its value to known instruction

values via some kind of table (depending on the implementation), and then

execute the equivalent native instruction. There is room for optimization

but it will never be very fast (relative to native code).

Therefore, run non-native object code only if you absolutely must. Below is

a binary compatibility table for Windows NT:

   System         Binary-Compatible on NT?

   ------        ------------------------

   Win16 apps     Yes (via Insignia's x86 emulation code)

   Win32 apps     No  (must re-compile)

   POSIX apps     No  (POSIX is a source-code standard)(1)

   OS/2 1.x apps  No  (Don't run on non-x86 machines at all)(2)

Notes: (1) POSIX 1003.1 is a C-language source-level standard for basic

operating system services. POSIX applications don't need to be binary-

compatible even on the same instruction set! That is, a POSIX application

compiled and linked for SCO on x86 will NOT run on x86 Windows NT POSIX or

x86 Sun/Interactive POSIX. (2) OS/2 1.x support is technically feasible but

would have required more work on the non-Intel platforms, and was not

considered a high priority.

The Hardware Abstraction Layer (HAL)

------------------------------------

A common misconception is that the HAL should allow binary compatibility.

The Windows NT HAL has absolutely nothing to do with the issue discussed

above; that is, running code complied for processor X on processor Y. Nor

is the HAL akin to a "virtual machine" implementation; it does not simulate

anything. Rather, the HAL is simply an example of a good modular software

design that deals with the issue of differences in hardware design between

machines with the same instruction set (or between instruction sets).

The HAL provides a set of services to the rest of the Windows NT executive

that abstracts and "hides" the differences between low- level hardware-

software interfaces, such as with DMA controllers, programmable interrupt

controllers, clocks and timers, and so forth. In a typical pre-Windows NT

operating system, there is lots of code embedded throughout the operating

system (particularly in device drivers) that is specifically tied to

particular implementations of hardware services (a particular PIC, a

particular DMA chip, and so forth). If one of these hardware pieces is

changed, lots of code scattered throughout the system will break. As a

result, the hardware never changed and a typical 486/66 machine today uses

the same low-function hardware devices that appear in the IBM AT 286 (if

not the IBM PC itself).

In Windows NT, any other part of the OS (including the kernel and all

device drivers) that needs to deal with those low-level devices now uses

HAL services, and is therefore isolated from changes in the hardware. If

you change those hardware pieces you only need to change the HAL. This

results in at least the following two advantages:

 - A cleaner, easier to write and debug design for the OS and device

   drivers.

 - The real possibility for innovation and change in the underlying

   hardware.

But the HAL does not provide an abstract instruction set, or the services

necessary for running object code from processor X on processor Y. It is

possible to write an such as OS if you are willing to take the huge

performance hit, but Windows NT isn't it. And because a well-designed OS

such as Windows NT can provide a very complete level of source-code

compatibility across instruction sets, and therefore a relatively painless

way of getting native-code versions of Win32 applications, probably no one

will be willing to take that performance hit in a mainstream operating

system, no matter how fast the hardware.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: SubSys


INF: Win32 Graphical Setup Not Supported Over Network Drives

Article ID: Q98838

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The graphical setup for the Win32 Software Development Kit (SDK) does not

include support for installing to a remote network drive because paths and

other information need to be set on the local machine. If your drive is not

supported, you should use MANUAL.BAT to set up the Win32 SDK.

Additional reference words: 3.10

KBCategory: Setins

KBSubcategory: Setins


INF: Specifying Filenames Under the POSIX Subsystem

Article ID: Q99361

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

When specifying filenames under POSIX, use the format

   //C/subdir/executable.exe

to specify C:\SUBDIR\EXECUTABLE.EXE. If you fail to use this format, you

will receive ENAMETOOLONG as the errno.

NOTE: The filenames are case-sensitive.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: Subsys


INF: Detecting Windows NT from an MS-DOS Application

Article ID: Q100290

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

There are calls that DOS applications can make that are not supported under

Windows NT. For example, calling Interrupt 25h to read the disk is not

supported under Windows NT. Therefore, in some cases DOS applications will

need to know whether or not they are running under Windows NT.

Interrupt 21h, function 3306h can be used by MS-DOS applications to detect

whether or not they are running under Windows NT. On return, registers BL

and BH will contain the operating system major and minor numbers,

respectively. If your application is running under Windows NT, the return

will be:

   BL = 5

   BH = 50

MORE INFORMATION

================

Note that it is important to check both BL and BH, because MS-DOS 5.0 will

also return a 5 in BL.

The following code demonstrates how to detect the operating system version

from an MS-DOS application:

Sample Code

-----------

#include <stdio.h>

#include <stdlib.h>

#include <io.h>

void main()

{

   unsigned char cbh = 0;

   unsigned char cbl = 0;

   unsigned char cdl = 0;

   unsigned char cdh = 0;

   _asm {

      mov ax, 3306h

      int 21h

      mov cbh, bh

      mov cbl, bl

   }

   printf( "After int 21h\n" );

   printf( "%d, %d (bh, bl)\n", cbh, cbl );

}

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: SubSys


INF: LIM-EMS Memory Limitations in a Windows NT VDM

Article ID: Q101189

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

A Windows NT virtual MS-DOS machine (VDM) session is LIM-EMS 4.0

compatible; however, each VDM is limited to 16 megabytes (MB) of memory.

A VDM is an MS-DOS session created whenever a user starts an MS-DOS

application on Windows NT. Windows NT allows any number of MS-DOS

applications to run simultaneously, each in its own address space.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: SubSys


INF: SHARE.EXE Functionality Built into Windows NT

Article ID: Q101191

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The functionality of the MS-DOS SHARE.EXE utility is built into the Windows

NT kernel. Any application or application programming interface (API) that

relies on the SHARE.EXE functionality is automatically supported. This

functionality cannot be disabled.

MORE INFORMATION

================

If you run the MS-DOS version of SHARE.EXE, you will receive a message

stating that SHARE is already installed. The Windows NT MS-DOS emulation

hooks Interrupt 2Fh function 10H and always returns a status indicating

that SHARE is installed.

If you run an MS-DOS application and it complains that SHARE.EXE is not

installed, the application may be searching the AUTOEXEC.BAT file for a

"share" string rather than using the proper Interrupt 2Fh interface.

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: SubSys


INF: LAN Manager API Support in OS/2 Subsystem

Article ID: Q101227

--------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

--------------------------------------------------------------------

The following is a list of Microsoft LAN Manager APIs that are supported by

the OS/2 subsystem:

   NetAccessAdd

   NetAccessGetInfo

   NetAccessSetInfo

   NetAccessSetDel

   NetBios v3.0

   NetBiosClose

   NetBiosGetInfo

   NetBiosOpen

   NetBiosSubmit

   NetGetDCName

   NetHandleGetInfo

   NetMessageBufferSend

   NetServerDiskEnum

   NetServerEnum2

   NetServerGetInfo

   NetServiceControl

   NetServiceEnum

   NetServiceGetInfo

   NetServiceInstall

   NetShareAdd

   NetShareDel

   NetShareEnum

   NetShareGetInfo

   NetUseAdd

   NetUseDel

   NetUseEnum

   NetUseGetInfo

   NetUserEnum

   NetUserGetInfo

   NetWkstaGetInfo

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: SubSys


INF: How POSIX Applications are Recognized

Article ID: Q101770

--------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

--------------------------------------------------------------------

The presence of the IMAGE_SUBSYSTEM_POSIX_CUI flag in the Subsystem

field of the image's optional header means that the application is a

32-bit POSIX application.

Additional reference words: 3.10

KBCategory: Prg

KBSubCategory: SubSys


INF: Determining Whether a WOW App is Running in Enhanced Mode

Article ID: Q101893

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Windows NT and Windows NT Advanced Server will run a Windows 3.1

application in 386 enhanced mode on X86 machines (standard mode on RISC

machines). The proper way to determine whether a Windows 3.1 application is

in enhanced mode is to call GetWinFlags() and do a bit test for

WF_ENHANCED. This method is described on pages 486-487 in the Windows 3.1

Software Development Kit (SDK) "Programmer's Reference, Volume 2:

Functions."

MORE INFORMATION

================

Calling Interrupt 2F with AX=1600h

----------------------------------

This method, which is described in the Windows 3.1 Device Development Kit

(DDK) checks to see whether a 386 memory manager is running. If Windows 3.1

is running in enhanced mode, it returns AL = 3 and 2 for standard mode.

Windows NT's WOW (Windows 16 on Windows NT) returns AL=0, which means

enhanced mode Windows is not running.

DWORD GetWinFlags()

-------------------

The GetWinFlags() function retrieves the current Windows system and

memory configuration.

The configuration returned by GetWinFlags() can be a combination of the

following values:

   Value          Meaning

   ----------------------------------------------------------------

   WF_80x87       System contains an Intel math coprocessor.

   WF_CPU286      System CPU is an 80286.

   WF_CPU386      System CPU is an 80386.

   WF_CPU486      System CPU is an i486.

   WF_ENHANCED    Windows is running in 386-enhanced mode. The WF_PMODE

                  flag is always set when WF_ENHANCED is set.

   WF_PAGING      Windows is running on a system with paged memory.

   WF_PMODE       Windows is running in protected mode. In Windows 3.1,

                  this flag is always set.

   WF_STANDARD    Windows is running in standard mode. The WF_PMODE

                  flag is always set when WF_STANDARD is set.

   WF_WIN286      Same as WF_STANDARD.

   WF_WIN386      Same as WF_ENHANCED.

NOTE: When running in Windows NT, WF_WINNT will also be returned to tell

the Windows 16 application that you are running in Windows NT.

Example:

The following example uses the GetWinFlags() function to display

information about the current Windows system configuration:

Sample Code

-----------

int len;

char szBuf[80];

DWORD dwFlags;

dwFlags = GetWinFlags();

len = sprintf(szBuf, "system %s a coprocessor",

    (dwFlags & WF_80x87) ? "contains" : "does not contain");

TextOut(hdc, 10, 15, szBuf, len);

len = sprintf(szBuf, "processor is an %s",

    (dwFlags & WF_CPU286) ? "80286" :

    (dwFlags & WF_CPU386) ? "80386" :

    (dwFlags & WF_CPU486) ? "i486" : "unknown");

TextOut(hdc, 10, 30, szBuf, len);

len = sprintf(szBuf, "running in %s mode",

    (dwFlags & WF_ENHANCED) ? "enhanced" : "standard");

TextOut(hdc, 10, 45, szBuf, len);

len = sprintf(szBuf, "%s WLO",

    (dwFlags & WF_WLO) ? "using" : "not using");

TextOut(hdc, 10, 60, szBuf, len);

Additional reference words: 3.10

KBCategory: Prg

KBSubcategory: SubSys


PRB: Error in Win32 SDK Install Program MANUAL.BAT

Article ID: Q103245

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SYMPTOMS

========

When installing the Win32 SDK with an unsupported CD-ROM, Microsoft

recommends booting MS-DOS and running MANUAL.BAT. This results in the

following error:

   invalid switch -  /i

WORKAROUND

==========

One workaround is to copy the MANUAL.BAT file to the hard disk and remove

the /i switches on the xcopy command lines. For example, if you copied the

file to C:\MANUAL.BAT and wanted to install the Win32 SDK with the

unsupported CD-ROM to drive c, the next step would be to switch back to the

CD-ROM and run C:\MANUAL.BAT C:.

In addition, a corrected copy of the MANUAL.BAT file was uploaded to

Library 8 of the MSWIN32 forum on CompuServe:

   SETUP.ZIP/Bin  Bytes:   10507, Count:    0, 02-Sep-93

   Last:**Never**

   Title   : Manual Bat Installation Helper Tools

   Keywords: SETUPSDK MANUAL SETUP FIX TOOL

   This file contains: MANUAL.BAT & SETUPSDK.EXE

   MANUAL.BAT is the fixed version of same-named file found on the

   Win32 SDK CD_ROM. This is the same file as found in MANUAL.ZIP as

   found in this forum.

   The SetupSDK tool will allow you to selectively create the various

   Program Manager groups and environment variables as are normally

   created using the "Graphical Installation" method. This tool can

   also be used to create these groups and variables for different

   user accounts on your local machine. This tool runs under Windows

   NT only.

Additional reference words: 3.10

KBCategory: Setins

KBSubcategory: Setins


INF: Symbolic Information for System DLLs

Article ID: Q103862

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

The debugging information for the system dynamic-link libraries (DLLs)

is contained separately in files with a .DBG extension. The Win32 SDK

setup, SETUPSDK, will install the following .DBG files by default in

<SYSTEMROOT>\SYMBOLS\DLL:

   ADVAPI32.DBG           OLECLI32.DBG

   COMDLG32.DBG           OLESVR32.DBG

   CRTDLL.DBG             RASAPI32.DBG

   DLCAPI.DBG             RPCNS4.DBG

   GDI32.DBG              RPCRT4.DBG

   INETMIB1.DBG           SHELL32.DBG

   KERNEL32.DBG           USER32.DBG

   LMMIB2.DBG             VDMDBG.DBG

   LZ32.DBG               VERSION.DBG

   MGMTAPI.DBG            WIN32SPL.DBG

   MPR.DBG                WINMM.DBG

   NDDEAPI.DBG            WINSTRM.DBG

   NETAPI32.DBG           WSOCK32.DBG

   NTDLL.DBG

Note that these files are not installed by the alternative Win32 SDK

install method, MANUAL.BAT. Therefore, WinDbg will warn that symbol

information cannot be found for each of the system DLLs called by the

debuggee.

These .DBG files can be manually installed by copying them from the

SDK CD. For x86, they are located in \SUPPORT\DEBUG\I386\SYMBOLS\DLL.

For MIPS, they are located in \SUPPORT\DEBUG\MIPS\SYMBOLS\DLL. Note

that there are more than 200 .DBG files in each of these directories.

MORE INFORMATION

================

There are also debugging versions of the system DLLs that can be

installed by using SWITCH.BAT, which is located on the CD in

\SUPPORT\DEBUGDLL. Refer to page 11 of the "Getting Started" manual

and the batch file itself for more information.

Additional reference words: 3.10

KBCategory: Setins

KBSubcategory: Setins


PRB: Win32 SDK and VC++ NT Help Files Are Incompatible

Article ID: Q104378

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

The Win32 API help file that accompany the Win32 SDK (that is, API32WH.HLP)

are incompatible with Windows Help files from the Visual C++ 32-bit

edition.

SYMPTOMS

========

Choosing the Search Plus button from within Visual C++ for Windows NT

Windows Help with a copy of a help file from the Win32 SDK produces a

"Missing or Old Index" error.

CAUSE

=====

The version of API32WH.HLP for Visual C++ for Windows NT is indexed with

several other help files to make it easy to search for terms and keywords

in several files at once. The Visual C++ Setup program writes the name of

the new index file into the Windows NT registry, and this name is different

than the name of the index file included with the Win32 SDK. If you

subsequently open API32WH.HLP from the Win32 SDK and use the full-text

search feature (the Find button), you will receive an error message about

an old or missing index file.

RESOLUTION

==========

If you have previously installed the Win32 SDK for Windows NT, after

installing Visual C++ for Windows NT, you should use only the version of

the Win32 application programming interface (API) help file (API32WH.HLP)

installed with Visual C++ for Windows NT. The Setup program installs this

file by default in the \HELP subdirectory under the directory that you have

chosen for Visual C++, or in a help subdirectory that you explicitly

choose.

For more information about moving from the Win32 SDK to Visual C++ for

Windows NT, see the MIGRATE.HLP help file.

Additional reference words: 3.10

KBCategory: Setins

KBSubcategory: Setins


INF: Migrating Windows NT Program Groups and the Desktop

Article ID: Q105298

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

There are a variety of ways of migrating groups under Windows NT. All

of the desktop information is located in the registry. By selectively

saving and restoring particular keys, you may restore your program

groups and desktop.

MORE INFORMATION

================

Note that modifying the registry is a potentially risky operation;

data loss is possible. You may want to back up your profile, which is

located in <SYSTEMROOT>\SYSTEM32\CONFIG and is usually a combination

of the username, some digits, and no extension. Your profile is locked

by the system when you are logged in to that account, however, so you

must copy it from another account or from MS-DOS.

The following is the procedure to save the desktop information:

1. Make sure you have Administrative access.

2. Run REGEDT32.EXE.

3. Select HKEY_CURRENT_USER\Program Groups.

4. From the Registry menu, choose Save Key.

5. Save the key (save as PROGRAM.REG).

6. Repeat steps 3-5 to save the following key:

      HKEY_CURRENT_USER\

      Software\

      Microsoft\

      Windows NT\

      Current Version\

      Program Manager\

      Groups

   (save as GROUPS.REG)

8. Repeat steps 3-5 to save the following key:

      HKEY_CURRENT_USER\Control Panel

   (save as CTRLPNL.REG)

PROGRAM.REG and GROUPS.REG have the information necessary to restore

the program groups, and CTRLPNL.REG contains the information necessary

to restore the desktop.

Procedure to restore registry keys:

 1. Back up your profile.

 2. Run REGEDT32.EXE.

 3. Select the key you want to restore (see steps 3, 6, and 7 above).

 4. Write down the exact name, spelling, and location of the key.

5. From the Edit menu, choose Delete and verify deletion of the key.

 6. Select the parent key of the key you just deleted.

 7. From the Edit menu, choose Add Key and type in the exact name of the

    deleted key. Don't worry about the Class field. Choose OK. The key

    should reappear in its position, but it will be empty.

 8. Select the key that you just created.

 9. From the Registry menu, choose Restore.

10. Find and select the file in which you saved the old key (for example,

    PROGRAM.REG). The saved key will be restored in the position that

    you selected.

11. Repeat for all keys you want to restore. When you are finished,

    exit REGEDT32 and log off. When you log back on, the groups and

    desktop should be restored.

Additional reference words: 3.10

KBCategory: Setins

KBSubcategory: Setins


INF: Starting and Terminating 16-Bit Windows Applications

Article ID: Q105676

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

A 16-bit Windows application running under Windows NT is running as a

thread in a single virtual MS-DOS machine (VDM). These threads are

nonpreemptively scheduled. A 16-bit Windows application shares an address

space and an input queue with other 16-bit Windows applications. Objects

created by a thread (application) are owned by the thread (application).

This environment is called WOW (Windows on Win32).

When a 16-bit application is started via CreateProcess(), the process

handle and the thread handle contained in the PROCESS_INFORMATION structure

are pseudo-handles. The only application programming interfaces (APIs) that

can use the process handle are WaitForSingleObject(),

WaitForMultipleObjects(), and WaitForInputIdle().

A common question is "How can I terminate a 16-bit process from a 32-bit

process?" However, as implied above, PROCESS_INFORMATION.hProcess cannot be

used in TerminateProcess() and PROCESS_INFORMATION.dwThreadId cannot be

used in PostThreadMessage().

One way to terminate an individual 16-bit Windows application is to

enumerate the desktop windows using EnumWindows(), determine which is the

correct window, obtain the thread ID with GetWindowThreadProcessId(), and

post a WM_QUIT message via PostThreadMessage() to terminate the

application.

Another way to terminate an individual 16-bit Windows application is to use

the TOOLHELP APIs. Use TaskFirst() and TaskNext() to enumerate the tasks,

determine which is the correct task, and call TerminateApp() to kill the

application. The Windows SDK sample THSAMPLE demonstrates how this can be

done.

Additional reference words: 3.10 win16

KBCategory: Prg

KBSubcategory: SubSys


INF: Troubleshooting Win32s 1.1 Installation Problems

Article ID: Q106715

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32s version 1.1

----------------------------------------------------------------------

SUMMARY

=======

The installation guide for Win32s version 1.1 that is included in the Win32

SDK recommends running Freecell to verify that the installation was

successful. This article discusses some of the errors that may occur when

trying to run Freecell on an unsuccessful install. The article also

contains a list of corrective actions to help you reinstall Win32s.

MORE INFORMATION

================

One of the following errors may occur when running Freecell if the

installation is not successful:

 - File Error: Cannot find OLECLI.DLL

   -or-

 - Win32s - Error:

   Improper installation. Win32s requires WIN32S.EXE and WIN32S16.DLL to

   run. Reinstall Win32s.

   -or-

 - Win32s - Error:

   Improper installation.  Windows requires w32s.386 in order to run.

   Reinstall Win32s.

   -or-

 - Error: Cannot find file freecell.exe (or one of its components)...

Another possible symptom is that the display is corrupted as soon as you

run FreeCell.

Check the following when Win32s does not install correctly:

 - If you are having video problems, check to see if you have an S3 video

   card. Certain S3 drivers do not work with Win32s. Either use the generic

   drivers shipped with Windows or contact your video card manufacturer for

   an updated driver.

 - If you have a printer driver by LaserMaster, delete it or comment it out

   because it interferes with installing Win32s. Then reboot the computer

   so that the changes you made will take effect. After you successfully

   reinstall Win32s, reinstall the driver or remove the comment characters.

   The driver interferes with installing Win32s because the LaserMaster

   drivers create a WINSPOOL device . The extension is ignored when the

   filename portion of a path matches a device name. As a result, when

   Setup tries to write to WINSPOOL.DRV, it fails, because it attempts to

   write to WINSPOOL. In fact, any Win32 application that tries to link to

   WINSPOOL.DRV also fails; however, most Win32 applications that print

   under Win32s do not use the WINSPOOL application programming interfaces

   (APIs) because they are not supported in Win32s. As a result, you can

   usually just disable this driver while installing Win32s and then

   reenable it afterwards.

 - Delete the \WIN32S directory, the \WIN32APP directory, W32SYS.DLL,

   W32S16.DLL, and WIN32S.EXE from your hard drive. Although it is possible

   to install Win32s on top of an old installation of Win32s, it is better

   to remove the old files before installing the new ones.

 - Edit the WIN32S.INI file on your hard drive. Change the line(s) SETUP =

   1 to read SETUP = 0.

 - Make sure that paging is enabled. From the Control Panel, select the 386

   Enhanced icon, choose Virtual Memory, and choose Change. Verify that the

   drive type is not set to none. The type can be set to either temporary

   or permanent.

 - Make sure that SHARE is enabled. Edit AUTOEXEC.BAT and add the following

   line if it is not already there:

      C:\DOS\SHARE.EXE

 - Reboot your computer and reinstall Win32s.

If you still receive errors when running Freecell, compare the binaries on

your hard drive with those on the CD. Use the MS-DOS program FILECOMP.EXE,

COMP.EXE, or FC.EXE and do a binary compare. For example, if you have the

Win32 SDK CD, type the following:

   fc /b <windir>\win32s\w32s.386 <cd>:\mstools\win32s\nodebug\w32s.386

If you have the 32-bit Visual C++ CD, type the following:

   fc /b <windir>\win32s\w32s.386 <cd>:\msvc32s\win32s\retail\w32s.386

The results of the compare will be, "FC: no differences encountered", if

the binaries were correctly installed. If the binaries are not the same,

you might have a bad copy of the files or a bad CD.

As a last resort, you can try reinstalling Win32s that shipped in the

Visual C++ 32-bit edition. There seems to be a slight difference between

the SETUP.EXE program on the Win32 SDK CD and the SETUP.EXE on the Visual

C++ CD. If you try installing from the 32-bit Visual C++ CD, you should NOT

remove the \WIN32APP or \FREECELL directory or any of the Freecell files.

The Visual C++ CD does not contain Freecell.

NOTE: Using Freecell Help will generate errors, including "Routine Not

Found" or "Help Topic Does Not Exist." The generation of these errors has

nothing to do with whether or not Win32s is installed correctly.

FREECELL.HLP was meant to be used with WINHLP32.EXE. FREECELL.HLP uses the

advanced features of WINHLP32 for full-text searching. WINHELP.EXE, which

runs on Windows 3.1, does not support this. As a result, each time

FREECELL.HLP tries to bind the Find button to the full-text searching APIs,

it fails, and Windows Help displays the message box. You can still read

most of the information in the help file. You can use the Search button to

do keyword searches.

Additional reference words: 1.10

KBCategory: Setins

KBSubcategory: W32s


INF: Making a Callback When Using Generic Thunks

Article ID: Q108229

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT

   version 3.1

----------------------------------------------------------------------

SUMMARY

=======

Generic Thunks are provided so that a 16-bit application can load and use a

32-bit dynamic-link library (DLL) under Windows NT. To see a simple example

using Generic Thunks, please see the following article(s) in the Microsoft

Knowledge Base:

   ARTICLE-ID: Q104009

   TITLE     : Calling a Win32 DLL from a Win16 Application Under WOW

This article extends this sample a step further and shows one way in which

you might implement a callback from a 32-bit DLL to the 16-bit application

that loaded it.

MORE INFORMATION

================

Suppose that you had two functions in a 16-bit application that you wanted

to be able to call from a 32-bit DLL that the application has loaded via

Generic Thunks:

   void MyFunc1( UINT );

   void MyFunc2( UINT );

The following steps can be used to accomplish this task:

1. Define function codes for the two functions and a unique message:

      #define MYFUNC1  1

      #define MYFUNC2  2

      #define WM_APP   WM_USER + 101

2. Have the 16-bit application pass its window handle to the 32-bit DLL.

   Note that it should pass it as a 32-bit value. To convert the window

   handle, simply put 0xffff in the upper word, as follows:

      (DWORD) hWnd | 0xffff0000

3. From the 32-bit DLL, call SendMessage() with:

    - The window handle obtained in step 2.

    - WM_APP.

    - The function code for the function that you wish to call.

    - Any data that you wish to pass to the function.

   For example:

      SendMessage( hWnd, WM_APP, MYFUNC1, dwVar1 );

      SendMessage( hWnd, WM_APP, MYFUNC2, dwVar2 );

4. In the 16-bit application, switch on wParam to determine which function

   to call, similar to the dispatch function used in Universal Thunks, and

   pass the parameter that is contained in lParam:

      case WM_APP:

         switch( wParam ) {

            case MYFUNC1:

               MyFunc1( lParam );

               break;

            case MYFUNC2:

               MyFunc2( lParam );

               break;

         }

         break;

Additional reference words: 3.10

KBCagegory: Prg

KBSubcategory: SubSys


INF: Running a Win16 Application in Its Own VDM

Article ID: Q115235

----------------------------------------------------------------------

The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

   version 3.5

----------------------------------------------------------------------

SUMMARY

=======

The Windows NT, version 3.1, Windows on Win32 (WOW) supports running all

Windows 3.x (Win16) applications in one virtual machine (VM). These

applications share an address space, just as they do on Windows. The

Windows NT, version 3.5, WOW supports running a Win16 application in its

own VM, which gives the application its own address space.

In order to programmatically start a Win16 application in its own VM,

start the application with CreateProcess() and then specify the flag

CREATE_SEPARATE_WOW_VDM.

To specify a Win16 application started from the command prompt to run in

its own address space, use the following syntax:

   start /SEPARATE <filename>

To specify a Win16 application started from the Program Manager to run in

its own address space, check the following item in the Program Item

Properties for the application or in the Run dialog box, which can be

selected from the Program Manager's File menu:

   Run in Separate Memory Space

NOTE: This option is not the default, nor is there any way to make it

the default.

MORE INFORMATION

================

Allowing a Win16 application to run in a separate address space provides

for more robust operation, because the application is isolated from other

Win16 applications. However, the downside is twofold:

 - WOW VMs require approximately 2500K of private memory on x86 machines.

 - There is no shared memory between WOW VMs. Therefore, Win16

   applications that rely on shared memory cannot be run in separate

   VMs. As an alternative, use DDE or OLE, because they can be used by

   an application in one VM to communicate with an application in

   another VM.

Additional reference words: 3.50

KBCategory: Prg

KBSubcategory: Subsys